You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2008/06/07 23:59:04 UTC

svn commit: r664402 [3/4] - in /myfaces/tomahawk/trunk/core12: ./ src/ src/main/ src/main/conf/ src/main/conf/META-INF/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/myfaces/ src/main/java/org/apache/myfaces/compo...

Added: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlCheckboxRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlCheckboxRenderer.java?rev=664402&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlCheckboxRenderer.java (added)
+++ myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlCheckboxRenderer.java Sat Jun  7 14:59:02 2008
@@ -0,0 +1,484 @@
+/*
+ * 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.renderkit.html.ext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.component.UserRoleUtils;
+import org.apache.myfaces.shared_tomahawk.component.DisplayValueOnlyCapable;
+import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
+import org.apache.myfaces.component.html.ext.HtmlSelectManyCheckbox;
+import org.apache.myfaces.custom.checkbox.HtmlCheckbox;
+import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlCheckboxRendererBase;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
+
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UISelectMany;
+import javax.faces.component.UISelectBoolean;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.convert.Converter;
+import javax.faces.model.SelectItem;
+import javax.faces.model.SelectItemGroup;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+
+
+/**
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC"
+ *   family = "org.apache.myfaces.Checkbox"
+ *   type = "org.apache.myfaces.Checkbox"
+ * 
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC"
+ *   family = "javax.faces.SelectBoolean"
+ *   type = "org.apache.myfaces.Checkbox"
+ *   
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC"
+ *   family = "javax.faces.SelectMany"
+ *   type = "org.apache.myfaces.Checkbox"
+ * 
+ * @author Manfred Geiler (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+public class HtmlCheckboxRenderer
+        extends HtmlCheckboxRendererBase
+{
+    private static final Log log = LogFactory.getLog(HtmlCheckboxRenderer.class);
+
+    private static final String PAGE_DIRECTION = "pageDirection";
+
+    private static final String LINE_DIRECTION = "lineDirection";
+
+    private static final String LAYOUT_SPREAD = "spread";
+
+    public void encodeEnd(FacesContext context, UIComponent component) throws IOException
+    {
+        if (context == null) throw new NullPointerException("context");
+        if (component == null) throw new NullPointerException("component");
+
+        if (component instanceof HtmlCheckbox)
+        {
+            renderSingleCheckbox(context, (HtmlCheckbox)component);
+        }
+        else if (component instanceof DisplayValueOnlyCapable && HtmlRendererUtils.isDisplayValueOnly(component))
+        {
+            HtmlRendererUtils.renderDisplayValueOnlyForSelects(context, component);
+        }
+        else if (component instanceof UISelectMany)
+        {
+            String layout = getLayout((UISelectMany)component);
+            if (layout != null && layout.equals(LAYOUT_SPREAD))
+            {
+                return; //checkbox inputs are rendered by spread checkbox components
+            }
+            else
+            {
+                super.encodeEnd(context, component);
+            }
+        }
+        else if(component instanceof UISelectBoolean)
+        {
+            super.encodeEnd(context,component);
+        }
+        else
+        {
+            throw new IllegalArgumentException("Unsupported component class " + component.getClass().getName());
+        }
+    }
+
+    public void renderCheckboxList(FacesContext facesContext,
+            UISelectMany selectMany) throws IOException
+    {
+        final String layout = getLayout(selectMany);
+        if (layout != null)
+        {
+            Converter converter = getConverter(facesContext, selectMany);
+            if (layout.equals(PAGE_DIRECTION))
+            {
+                renderCheckboxListVertically(facesContext, selectMany,
+                        converter);
+            }
+            else if (layout.equals(LINE_DIRECTION))
+            {
+                renderCheckboxListHorizontally(facesContext, selectMany,
+                        converter);
+            }
+            else
+            {
+                log.error("Wrong layout attribute for component "
+                        + selectMany.getClientId(facesContext) + ": " + layout);
+            }
+        }
+    }
+
+    protected void renderCheckboxListHorizontally(FacesContext facesContext,
+            UISelectMany selectMany, Converter converter) throws IOException
+    {
+        Set lookupSet = RendererUtils.getSubmittedValuesAsSet(facesContext,
+                selectMany, converter, selectMany);
+        boolean useSubmittedValues = lookupSet != null;
+        if (!useSubmittedValues)
+        {
+            lookupSet = RendererUtils.getSelectedValuesAsSet(facesContext,
+                    selectMany, converter, selectMany);
+        }
+
+        ResponseWriter writer = facesContext.getResponseWriter();
+        writer.startElement(HTML.TABLE_ELEM, selectMany);
+        HtmlRendererUtils.renderHTMLAttributes(writer, selectMany,
+                HTML.SELECT_TABLE_PASSTHROUGH_ATTRIBUTES);
+        HtmlRendererUtils.writeIdIfNecessary(writer, selectMany, facesContext);
+
+        final int numRows = getLayoutWidth(selectMany);
+        for (int i = 0; i < numRows; i++)
+        {
+            renderRowForHorizontal(facesContext, selectMany, converter,
+                    lookupSet, writer, numRows, i);
+        }
+
+        writer.endElement(HTML.TABLE_ELEM);
+    }
+
+    protected void renderRowForHorizontal(FacesContext facesContext,
+            UISelectMany selectMany, Converter converter, Set lookupSet,
+            ResponseWriter writer, int totalRows, int rowNum)
+            throws IOException
+    {
+
+        writer.startElement(HTML.TR_ELEM, selectMany);
+        int colNum = 0;
+        List items = RendererUtils.getSelectItemList(selectMany);
+        for (int count = rowNum; count < items.size(); count++)
+        {
+            int mod = count % totalRows;
+            if (mod == rowNum)
+            {
+                colNum++;
+                SelectItem selectItem = (SelectItem) items.get(count);
+                writer.startElement(HTML.TD_ELEM, selectMany);
+                renderGroupOrItemCheckbox(facesContext, selectMany, selectItem,
+                        lookupSet != null, lookupSet, converter, false);
+                writer.endElement(HTML.TD_ELEM);
+            }
+        }
+        int totalItems = items.size();
+        int totalCols = (totalItems / totalRows);
+        if (totalItems % totalRows != 0)
+        {
+            totalCols++;
+        }
+        if (colNum < totalCols)
+        {
+            writer.startElement(HTML.TD_ELEM, selectMany);
+            writer.endElement(HTML.TD_ELEM);
+        }
+        writer.endElement(HTML.TR_ELEM);
+    }
+
+    protected void renderCheckboxListVertically(FacesContext facesContext,
+            UISelectMany selectMany, Converter converter) throws IOException
+    {
+
+        Set lookupSet = RendererUtils.getSubmittedValuesAsSet(facesContext,
+                selectMany, converter, selectMany);
+        boolean useSubmittedValues = lookupSet != null;
+        if (!useSubmittedValues)
+        {
+            lookupSet = RendererUtils.getSelectedValuesAsSet(facesContext,
+                    selectMany, converter, selectMany);
+        }
+
+        ResponseWriter writer = facesContext.getResponseWriter();
+        writer.startElement(HTML.TABLE_ELEM, selectMany);
+        HtmlRendererUtils.renderHTMLAttributes(writer, selectMany,
+                HTML.SELECT_TABLE_PASSTHROUGH_ATTRIBUTES);
+        HtmlRendererUtils.writeIdIfNecessary(writer, selectMany, facesContext);
+
+        List items = RendererUtils.getSelectItemList(selectMany);
+        int totalItems = items.size();
+        for (int count = 0; count < totalItems; count++)
+        {
+            writer.startElement(HTML.TR_ELEM, selectMany);
+            final int numCols = getLayoutWidth(selectMany);
+            for (int i = 0; i < numCols; i++)
+            {
+                writer.startElement(HTML.TD_ELEM, selectMany);
+                if (count < totalItems)
+                {
+                    SelectItem selectItem = (SelectItem) items.get(count);
+                    renderGroupOrItemCheckbox(facesContext, selectMany,
+                            selectItem, lookupSet != null, lookupSet,
+                            converter, true);
+                }
+                writer.endElement(HTML.TD_ELEM);
+                if (i < numCols - 1)
+                {
+                    count += 1;
+                }
+            }
+            writer.endElement(HTML.TR_ELEM);
+        }
+        writer.endElement(HTML.TABLE_ELEM);
+    }
+
+    protected void renderGroupOrItemCheckbox(FacesContext facesContext,
+            UIComponent uiComponent, SelectItem selectItem,
+            boolean useSubmittedValues, Set lookupSet,
+            Converter converter, boolean pageDirectionLayout) throws IOException {
+        ResponseWriter writer = facesContext.getResponseWriter();
+        
+        boolean isSelectItemGroup = (selectItem instanceof SelectItemGroup);
+
+        if (isSelectItemGroup)
+        {
+            SelectItemGroup selectItemGroup = (SelectItemGroup) selectItem;
+            renderCheckboxGroup(facesContext, uiComponent, selectItemGroup,
+                    useSubmittedValues, lookupSet, converter,
+                    pageDirectionLayout);
+        }
+        else
+        {
+            UISelectMany selectMany = (UISelectMany) uiComponent;
+            Object itemValue = selectItem.getValue(); // TODO : Check here for getSubmittedValue. Look at RendererUtils.getValue
+            String itemStrValue = getItemStringValue(facesContext, selectMany,
+                    converter, itemValue);
+
+            boolean checked = (useSubmittedValues && lookupSet
+                    .contains(itemStrValue))
+                    || (!useSubmittedValues && lookupSet.contains(itemValue));
+
+            boolean disabled = selectItem.isDisabled();
+
+            writer.startElement(HTML.LABEL_ELEM, selectMany);
+            renderLabelClassIfNecessary(facesContext, selectMany, disabled);
+            writer.writeText(selectItem.getLabel(), null);
+            renderCheckbox(facesContext, selectMany, itemStrValue, disabled, checked, false,0);
+            writer.endElement(HTML.LABEL_ELEM);
+        }
+    }
+
+    protected void renderLabelClassIfNecessary(FacesContext facesContext,
+            UISelectMany selectMany, boolean disabled) throws IOException
+    {
+        String labelClass = null;
+        boolean componentDisabled = isDisabled(facesContext, selectMany);
+        if (componentDisabled || disabled)
+        {
+            labelClass = (String) selectMany.getAttributes().get(
+                    JSFAttr.DISABLED_CLASS_ATTR);
+        }
+        else
+        {
+            labelClass = (String) selectMany.getAttributes().get(
+                    JSFAttr.ENABLED_CLASS_ATTR);
+        }
+        if (labelClass != null)
+        {
+            ResponseWriter writer = facesContext.getResponseWriter();
+            writer.writeAttribute("class", labelClass, "labelClass");
+        }
+    }
+
+    protected void renderCheckboxGroup(FacesContext facesContext,
+            UIComponent uiComponent, SelectItemGroup selectItemGroup,
+            boolean useSubmittedValues, Set lookupSet,
+            Converter converter, boolean pageDirectionLayout) throws IOException {
+        ResponseWriter writer = facesContext.getResponseWriter();
+        UISelectMany selectMany = (UISelectMany)uiComponent;
+        writer.startElement(HTML.TABLE_ELEM, selectMany);
+        if (pageDirectionLayout)
+            writer.startElement(HTML.TR_ELEM, selectMany);
+        writer.startElement(HTML.TD_ELEM, selectMany);
+        writer.write(selectItemGroup.getLabel());
+        writer.endElement(HTML.TD_ELEM);
+        
+        if (pageDirectionLayout) {
+            writer.endElement(HTML.TR_ELEM);
+            writer.startElement(HTML.TR_ELEM, selectMany);
+        }
+        writer.startElement(HTML.TD_ELEM, selectMany);
+        writer.startElement(HTML.TABLE_ELEM, selectMany);
+        writer.writeAttribute(HTML.BORDER_ATTR, "0", null);
+
+        SelectItem[] selectItems = selectItemGroup.getSelectItems();
+        for (int i=0; i<selectItems.length; i++) {
+            renderGroupOrItemCheckbox(facesContext, selectMany, selectItems[i], useSubmittedValues, lookupSet, converter, pageDirectionLayout);
+        }
+        
+        writer.endElement(HTML.TABLE_ELEM);
+        writer.endElement(HTML.TD_ELEM);
+        if (pageDirectionLayout)
+            writer.endElement(HTML.TR_ELEM);
+        writer.endElement(HTML.TABLE_ELEM);
+    }
+
+    /**
+     * Determines the layout setting.  Defaults to
+     * <code>lineDirection</code> if not specified.
+     * @param selectMany the component
+     * @return the layout
+     */
+    protected String getLayout(UISelectMany selectMany) {
+        String layout = super.getLayout(selectMany);
+        if (layout == null) {
+            layout = LINE_DIRECTION;
+        }
+        return layout;
+    }
+    /**
+     * Gets the layout width.
+     * Returns the default layout width of 1 if the layout width
+     * is not set or is less than 1.  
+     * @param selectMany the component
+     * @return the layout width
+     */
+    protected int getLayoutWidth(UISelectMany selectMany) {
+        String layoutWidthString = null;
+        if (selectMany instanceof HtmlSelectManyCheckbox) {
+            layoutWidthString = ((HtmlSelectManyCheckbox) selectMany).getLayoutWidth();
+        } else {
+            layoutWidthString = (String) selectMany.getAttributes().get(JSFAttr.LAYOUT_WIDTH_ATTR);
+        }
+        final int defaultLayoutWidth = 1;
+        int layoutWidth = defaultLayoutWidth;
+        try {
+            if (layoutWidthString != null && layoutWidthString.trim().length() > 0) {
+                layoutWidth = Integer.parseInt(layoutWidthString);
+            }
+            if (layoutWidth < 1) {
+                layoutWidth = defaultLayoutWidth;
+            }
+        } catch (Exception e) {
+            layoutWidth = defaultLayoutWidth;
+        }
+        return layoutWidth;
+    }
+
+    protected void renderSingleCheckbox(FacesContext facesContext, HtmlCheckbox checkbox) throws IOException
+    {
+        String forAttr = checkbox.getFor();
+        if (forAttr == null)
+        {
+            throw new IllegalStateException("mandatory attribute 'for'");
+        }
+        int index = checkbox.getIndex();
+        if (index < 0)
+        {
+            throw new IllegalStateException("positive index must be given");
+        }
+
+        UIComponent uiComponent = checkbox.findComponent(forAttr);
+        if (uiComponent == null)
+        {
+            throw new IllegalStateException("Could not find component '" + forAttr + "' (calling findComponent on component '" + checkbox.getClientId(facesContext) + "')");
+        }
+        if (!(uiComponent instanceof UISelectMany))
+        {
+            throw new IllegalStateException("UISelectMany expected");
+        }
+
+        UISelectMany uiSelectMany = (UISelectMany)uiComponent;
+        Converter converter = getConverter(facesContext, uiSelectMany);
+        List selectItemList = RendererUtils.getSelectItemList(uiSelectMany);
+        if (index >= selectItemList.size())
+        {
+            throw new IndexOutOfBoundsException("index " + index + " >= " + selectItemList.size());
+        }
+
+        SelectItem selectItem = (SelectItem)selectItemList.get(index);
+        Object itemValue = selectItem.getValue();
+        String itemStrValue = getItemStringValue(facesContext, uiSelectMany, converter, itemValue);
+
+        //TODO: we must cache this Set!
+        Set lookupSet = RendererUtils.getSelectedValuesAsSet(facesContext, uiComponent, converter, uiSelectMany);
+
+        renderCheckbox(facesContext,
+                       uiSelectMany,
+                       itemStrValue,
+                       selectItem.getLabel(),
+                       isDisabled(facesContext,uiSelectMany),
+                       lookupSet.contains(itemStrValue), true);
+    }
+
+
+    protected boolean isDisabled(FacesContext facesContext, UIComponent uiComponent)
+    {
+        if (!UserRoleUtils.isEnabledOnUserRole(uiComponent))
+        {
+            return true;
+        }
+        else
+        {
+            return super.isDisabled(facesContext, uiComponent);
+        }
+    }
+
+    public void decode(FacesContext facesContext, UIComponent uiComponent)
+    {
+        if (uiComponent instanceof HtmlCheckbox)
+        {
+            //nothing to decode
+        }
+        else
+        {
+            super.decode(facesContext, uiComponent);
+        }
+    }
+
+    protected String getItemStringValue(FacesContext facesContext, UISelectMany selectMany, 
+            Converter converter, Object itemValue) {
+        String itemStrValue;
+        if (converter == null)
+        {
+            itemStrValue = itemValue.toString();
+        }
+        else
+        {
+            itemStrValue = converter.getAsString(facesContext, selectMany, itemValue);
+        }
+        return itemStrValue;
+    }
+
+    protected Converter getConverter(FacesContext facesContext,
+            UISelectMany selectMany)
+    {
+        Converter converter;
+        try
+        {
+            converter = RendererUtils.findUISelectManyConverter(facesContext,
+                    selectMany);
+        }
+        catch (FacesException e)
+        {
+            log.error("Error finding Converter for component with id "
+                    + selectMany.getClientId(facesContext));
+            converter = null;
+        }
+        return converter;
+    }
+
+}

Propchange: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlCheckboxRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlCheckboxRenderer.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlRadioRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlRadioRenderer.java?rev=664402&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlRadioRenderer.java (added)
+++ myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlRadioRenderer.java Sat Jun  7 14:59:02 2008
@@ -0,0 +1,201 @@
+/*
+ * 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.renderkit.html.ext;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.faces.FacesException;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.component.UISelectOne;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.convert.Converter;
+import javax.faces.model.SelectItem;
+
+import org.apache.myfaces.component.UserRoleUtils;
+import org.apache.myfaces.custom.radio.HtmlRadio;
+import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRadioRendererBase;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
+
+
+/**
+ * 
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC"
+ *   family = "org.apache.myfaces.Radio"
+ *   type = "org.apache.myfaces.Radio"
+ *    
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC"
+ *   family = "javax.faces.SelectOne"
+ *   type = "org.apache.myfaces.Radio"
+ * 
+ * @author Manfred Geiler (latest modification by $Author$)
+ * @author Thomas Spiegl
+ * @version $Revision$ $Date$
+ */
+public class HtmlRadioRenderer
+        extends HtmlRadioRendererBase
+{
+    //private static final Log log = LogFactory.getLog(HtmlRadioRenderer.class);
+
+    private static final String LAYOUT_SPREAD = "spread";
+
+    public void encodeEnd(FacesContext context, UIComponent component) throws IOException
+    {
+        if (context == null) throw new NullPointerException("context");
+        if (component == null) throw new NullPointerException("component");
+
+        if (component instanceof HtmlRadio)
+        {
+            renderRadio(context, (HtmlRadio)component);
+        }
+        else if (HtmlRendererUtils.isDisplayValueOnly(component))
+        {
+            HtmlRendererUtils.renderDisplayValueOnlyForSelects(context, component);
+        }
+        else if (component instanceof UISelectOne)
+        {
+            String layout = getLayout(component);
+            if (layout != null && layout.equals(LAYOUT_SPREAD))
+            {
+                return; //radio inputs are rendered by spread radio components
+            }
+            else
+            {
+                super.encodeEnd(context, component);
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException("Unsupported component class " + component.getClass().getName());
+        }
+    }
+
+    protected void renderRadio(FacesContext facesContext, HtmlRadio radio) throws IOException
+    {
+        String forAttr = radio.getFor();
+        if (forAttr == null)
+        {
+            throw new IllegalStateException("mandatory attribute 'for'");
+        }
+        int index = radio.getIndex();
+        if (index < 0)
+        {
+            throw new IllegalStateException("positive index must be given");
+        }
+
+        UIComponent uiComponent = radio.findComponent(forAttr);
+        if (uiComponent == null)
+        {
+            throw new IllegalStateException("Could not find component '" + forAttr + "' (calling findComponent on component '" + radio.getClientId(facesContext) + "')");
+        }
+        if (!(uiComponent instanceof UISelectOne))
+        {
+            throw new IllegalStateException("UISelectOne expected");
+        }
+
+        UISelectOne uiSelectOne = (UISelectOne)uiComponent;
+        Converter converter;
+        List selectItemList = RendererUtils.getSelectItemList(uiSelectOne);
+        if (index >= selectItemList.size())
+        {
+            throw new IndexOutOfBoundsException("index " + index + " >= " + selectItemList.size());
+        }
+
+        try
+        {
+            converter = RendererUtils.findUIOutputConverter(facesContext, uiSelectOne);
+        }
+        catch (FacesException e)
+        {
+            converter = null;
+        }
+
+        Object currentValue = RendererUtils.getObjectValue(uiSelectOne);
+        currentValue
+            = RendererUtils.getConvertedStringValue(facesContext, uiSelectOne,
+                                                    converter, currentValue);
+        SelectItem selectItem = (SelectItem)selectItemList.get(index);
+        String itemStrValue
+            = RendererUtils.getConvertedStringValue(facesContext, uiSelectOne,
+                                                    converter,
+                                                    selectItem.getValue());
+
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        //writer.startElement(HTML.LABEL_ELEM, uiSelectOne);
+        
+        //renderRadio(facesContext,
+        //            uiSelectOne,
+        //            itemStrValue,
+        //            selectItem.getLabel(),
+        //            selectItem.isDisabled(),
+        //            itemStrValue.equals(currentValue), false);
+        //writer.endElement(HTML.LABEL_ELEM);
+
+        //Render the radio component
+        String itemId = renderRadio(facesContext,
+                uiSelectOne,
+                itemStrValue,
+                selectItem.isDisabled(),
+                itemStrValue.equals(currentValue),
+                false,
+                index);        
+        
+        //Render the
+        // label element after the input
+        boolean componentDisabled = isDisabled(facesContext, uiSelectOne);
+        boolean itemDisabled = selectItem.isDisabled();
+        boolean disabled = (componentDisabled || itemDisabled);
+
+        HtmlRendererUtils.renderLabel(writer, uiSelectOne, itemId, selectItem.getLabel(), disabled);
+    }
+
+
+    protected boolean isDisabled(FacesContext facesContext, UIComponent uiComponent)
+    {
+        if (!UserRoleUtils.isEnabledOnUserRole(uiComponent))
+        {
+            return true;
+        }
+        else
+        {
+            return super.isDisabled(facesContext, uiComponent);
+        }
+    }
+
+
+    public void decode(FacesContext facesContext, UIComponent uiComponent)
+    {
+        if (uiComponent instanceof HtmlRadio)
+        {
+            //nothing to decode
+        }
+        else
+        {
+            super.decode(facesContext, uiComponent);
+        }
+    }
+
+}

Propchange: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlRadioRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlRadioRenderer.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlTableRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlTableRenderer.java?rev=664402&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlTableRenderer.java (added)
+++ myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlTableRenderer.java Sat Jun  7 14:59:02 2008
@@ -0,0 +1,1011 @@
+/*
+ * 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.renderkit.html.ext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.component.NewspaperTable;
+import org.apache.myfaces.component.html.ext.HtmlDataTable;
+import org.apache.myfaces.custom.column.HtmlColumn;
+import org.apache.myfaces.custom.column.HtmlSimpleColumn;
+import org.apache.myfaces.custom.crosstable.UIColumns;
+import org.apache.myfaces.renderkit.html.util.ColumnInfo;
+import org.apache.myfaces.renderkit.html.util.RowInfo;
+import org.apache.myfaces.renderkit.html.util.TableContext;
+import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
+import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase;
+import org.apache.myfaces.shared_tomahawk.util.ArrayUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIData;
+import javax.faces.component.ValueHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Renderer for the Tomahawk extended HtmlDataTable component.
+ *
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC"
+ *   family = "javax.faces.Data"
+ *   type = "org.apache.myfaces.Table" 
+ *   
+ * @author Manfred Geiler (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+public class HtmlTableRenderer extends HtmlTableRendererBase {
+    private static final Log log = LogFactory.getLog(HtmlTableRenderer.class);
+
+    /**
+     * DetailStamp facet name.
+     */
+    public static final String DETAIL_STAMP_FACET_NAME = "detailStamp";
+    private static final String BODY_STYLE_CLASS = "bodyStyleClass";
+    private static final String BODY_STYLE = "bodyStyle";
+
+    /**
+     * @param component dataTable
+     * @return number of layout columns
+     */
+    protected int getNewspaperColumns(UIComponent component) {
+        if (component instanceof NewspaperTable) {
+            // the number of slices to break the table up into */
+            NewspaperTable newspaperTable = (NewspaperTable) component;
+            return newspaperTable.getNewspaperColumns();
+        }
+        return super.getNewspaperColumns(component);
+    }
+
+    /**
+     * @param component dataTable
+     * @return component to display between layout columns
+     */
+    protected UIComponent getNewspaperTableSpacer(UIComponent component) {
+        if (component instanceof NewspaperTable) {
+            // the number of slices to break the table up into */
+            NewspaperTable newspaperTable = (NewspaperTable) component;
+            return newspaperTable.getSpacer();
+        }
+        return super.getNewspaperTableSpacer(component);
+    }
+
+    /**
+     * @param component dataTable
+     * @return whether dataTable has component to display between layout columns
+     */
+    protected boolean hasNewspaperTableSpacer(UIComponent component) {
+        if (null != getNewspaperTableSpacer(component)) {
+            return true;
+        }
+        return super.hasNewspaperTableSpacer(component);
+    }
+
+    /**
+     * @param component dataTable
+     * @return if the orientation of the has newspaper columns is horizontal
+     */
+    protected boolean isNewspaperHorizontalOrientation(UIComponent component) {
+        if (component instanceof NewspaperTable) {
+            // get the value of the newspaperOrientation attribute, any value besides horizontal
+            // means vertical, the default
+            NewspaperTable newspaperTable = (NewspaperTable) component;
+            return NewspaperTable.NEWSPAPER_HORIZONTAL_ORIENTATION.equals(newspaperTable.getNewspaperOrientation());
+        }
+        return super.isNewspaperHorizontalOrientation(component);
+    }
+
+    protected void startTable(FacesContext facesContext, UIComponent uiComponent) throws IOException {
+        boolean embedded = isEmbeddedTable(uiComponent);
+
+        if (!embedded) {
+            super.startTable(facesContext, uiComponent);
+        }
+    }
+
+    protected String determineHeaderFooterTag(FacesContext facesContext, UIComponent component, boolean header) {
+        if (isEmbeddedTable(component)) {
+            // we are embedded, so do not render the tfoot/thead stuff
+            return null;
+        }
+
+        return super.determineHeaderFooterTag(facesContext, component, header);
+    }
+
+    protected String determineHeaderCellTag(FacesContext facesContext, UIComponent component) {
+        if (isEmbeddedTable(component)) {
+            return HTML.TD_ELEM;
+        }
+
+        return HTML.TH_ELEM;
+    }
+
+    protected void renderTableHeaderOrFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component, UIComponent facet, String styleClass, String colElementName, int colspan, boolean isHeader) throws IOException {
+        if (isEmbeddedTable(component)) {
+            // embedded tables render the header/footer stuff using TD only
+            colElementName = HTML.TD_ELEM;
+        }
+
+        super.renderTableHeaderOrFooterRow(facesContext, writer, component, facet, styleClass, colElementName, colspan, isHeader);
+    }
+
+    protected boolean isEmbeddedTable(UIComponent uiComponent) {
+        boolean embedded = false;
+        if (uiComponent instanceof HtmlDataTable) {
+            HtmlDataTable table = (HtmlDataTable) uiComponent;
+            embedded = table.isEmbedded();
+        }
+        return embedded;
+    }
+
+    protected boolean isDetailStampAfterRow(UIComponent uiComponent) {
+        if (uiComponent instanceof HtmlDataTable) {
+            return "after".equals(((HtmlDataTable) uiComponent).getDetailStampLocation());
+        }
+
+        return true;
+    }
+
+    protected void endTable(FacesContext facesContext, UIComponent uiComponent) throws IOException {
+        boolean embedded = isEmbeddedTable(uiComponent);
+
+        if (!embedded) {
+            super.endTable(facesContext, uiComponent);
+        }
+    }
+
+    protected void beforeRow(FacesContext facesContext, UIData uiData) throws IOException {
+        super.beforeRow(facesContext, uiData);
+
+        if (!isDetailStampAfterRow(uiData)) {
+            renderDetailRow(facesContext, uiData);
+        }
+    }
+
+    protected void afterRow(FacesContext facesContext, UIData uiData) throws IOException {
+        super.afterRow(facesContext, uiData);
+
+        if (isDetailStampAfterRow(uiData)) {
+            renderDetailRow(facesContext, uiData);
+        }
+    }
+
+    /**
+     * @param facesContext
+     * @param uiData
+     * @throws IOException
+     */
+    private void renderDetailRow(FacesContext facesContext, UIData uiData) throws IOException {
+        UIComponent detailStampFacet = uiData.getFacet(DETAIL_STAMP_FACET_NAME);
+
+        if (uiData instanceof HtmlDataTable) {
+            HtmlDataTable htmlDataTable = (HtmlDataTable) uiData;
+
+            if (htmlDataTable.isCurrentDetailExpanded()) {
+
+                boolean embedded = false;
+                if (detailStampFacet != null) {
+                    embedded = isEmbeddedTable(detailStampFacet);
+                }
+
+                ResponseWriter writer = facesContext.getResponseWriter();
+
+                if (!embedded) {
+                    writer.startElement(HTML.TR_ELEM, uiData);
+                    writer.startElement(HTML.TD_ELEM, uiData);
+                    writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(uiData.getChildren().size()), null);
+                }
+
+                if (detailStampFacet != null) {
+                    RendererUtils.renderChild(facesContext, detailStampFacet);
+                }
+
+                if (!embedded) {
+                    writer.endElement(HTML.TD_ELEM);
+                    writer.endElement(HTML.TR_ELEM);
+                }
+            }
+        }
+    }
+
+    /**
+     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#encodeBegin(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
+     */
+    public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException {
+        if (uiComponent instanceof HtmlDataTable) {
+            HtmlDataTable htmlDataTable = (HtmlDataTable) uiComponent;
+            if (htmlDataTable.isRenderedIfEmpty() || htmlDataTable.getRowCount() > 0) {
+                super.encodeBegin(facesContext, uiComponent);
+            }
+        }
+        else {
+            super.encodeBegin(facesContext, uiComponent);
+        }
+    }
+
+    /**
+     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#encodeChildren(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
+     */
+    public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException {
+        if (component instanceof HtmlDataTable) {
+            HtmlDataTable htmlDataTable = (HtmlDataTable) component;
+            if (htmlDataTable.isRenderedIfEmpty() || htmlDataTable.getRowCount() > 0) {
+                super.encodeChildren(facesContext, component);
+            }
+        }
+        else {
+            super.encodeChildren(facesContext, component);
+        }
+    }
+
+    private boolean isGroupedTable(UIData uiData) {
+        if (uiData instanceof HtmlDataTable) {
+            List children = getChildren(uiData);
+            for (int j = 0, size = getChildCount(uiData); j < size; j++) {
+                UIComponent child = (UIComponent) children.get(j);
+                if (child instanceof HtmlSimpleColumn) {
+                    HtmlSimpleColumn column = (HtmlSimpleColumn) child;
+                    if (column.isGroupBy()) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;  //To change body of created methods use File | Settings | File Templates.
+    }
+
+    protected void beforeBody(FacesContext facesContext, UIData uiData) throws IOException {
+        if (isGroupedTable(uiData)) {
+            createColumnInfos((HtmlDataTable) uiData, facesContext);
+        }
+        super.beforeBody(facesContext, uiData);
+    }
+
+    private void createColumnInfos(HtmlDataTable htmlDataTable, FacesContext facesContext)
+        throws IOException {
+        int first = htmlDataTable.getFirst();
+        int rows = htmlDataTable.getRows();
+        int last;
+        int currentRowSpan = -1;
+        int currentRowInfoIndex = -1;
+
+        TableContext tableContext = htmlDataTable.getTableContext();
+        RowInfo rowInfo = null;
+        ColumnInfo columnInfo = null;
+        HtmlSimpleColumn currentColumn = null;
+        Map groupHashTable = new HashMap();
+
+        if (rows <= 0) {
+            last = htmlDataTable.getRowCount();
+        }
+        else {
+            last = first + rows;
+        }
+
+        //Loop over the Children Columns to find the Columns with groupBy Attribute true
+        List children = getChildren(htmlDataTable);
+        int nChildren = getChildCount(htmlDataTable);
+
+        for (int j = 0, size = nChildren; j < size; j++) {
+            UIComponent child = (UIComponent) children.get(j);
+            if (child instanceof HtmlSimpleColumn) {
+                currentColumn = (HtmlSimpleColumn) child;
+                if (currentColumn.isGroupBy()) {
+                    groupHashTable.put(new Integer(j), null);
+                }
+            }
+        }
+
+        boolean groupEndReached = false;
+
+        for (int rowIndex = first; last == -1 || rowIndex < last; rowIndex++) {
+            htmlDataTable.setRowIndex(rowIndex);
+            rowInfo = new RowInfo();
+            //scrolled past the last row
+            if (!htmlDataTable.isRowAvailable()) {
+                break;
+            }
+
+            Set groupIndexList = groupHashTable.keySet();
+            List currentColumnContent = null;
+            for (Iterator it = groupIndexList.iterator(); it.hasNext();) {
+                currentColumnContent = new ArrayList();
+                Integer currentIndex = (Integer) it.next();
+                currentColumn = (HtmlSimpleColumn) children.get(currentIndex.intValue());
+
+                if (currentColumn.isGroupByValueSet()) {
+                    currentColumnContent.add(currentColumn.getGroupByValue());
+                }
+                else {
+                    // iterate the children - this avoids to add the column facet too
+                    List currentColumnChildren = currentColumn.getChildren();
+                    if (currentColumnChildren != null) {
+                        collectChildrenValues(currentColumnContent, currentColumnChildren.iterator());
+                    }
+                }
+
+                if (!isListEqual(currentColumnContent, (List) groupHashTable.get(currentIndex)) &&
+                    currentRowInfoIndex > -1) {
+                    groupEndReached = true;
+                    groupHashTable.put(currentIndex, currentColumnContent);
+                }
+                else if (currentRowInfoIndex == -1) {
+                    groupHashTable.put(currentIndex, currentColumnContent);
+                }
+            }
+            currentRowSpan++;
+
+
+            for (int j = 0, size = nChildren; j < size; j++) {
+                columnInfo = new ColumnInfo();
+                if (groupHashTable.containsKey(new Integer(j)))  // Column is groupBy
+                {
+                    if (currentRowSpan > 0) {
+                        if (groupEndReached) {
+                            ((ColumnInfo)
+                                ((RowInfo)
+                                    tableContext.getRowInfos().get(currentRowInfoIndex - currentRowSpan + 1)).
+                                    getColumnInfos().get(j)).
+                                setRowSpan(currentRowSpan);
+                            columnInfo.setStyle(htmlDataTable.getRowGroupStyle());
+                            columnInfo.setStyleClass(htmlDataTable.getRowGroupStyleClass());
+                        }
+                        else {
+                            columnInfo.setRendered(false);
+                        }
+                    }
+                    else {
+                        columnInfo.setStyle(htmlDataTable.getRowGroupStyle());
+                        columnInfo.setStyleClass(htmlDataTable.getRowGroupStyleClass());
+                    }
+
+                }
+                else    // Column  is not group by
+                {
+                    if (groupEndReached) {
+                        ((ColumnInfo)
+                            ((RowInfo)
+                                tableContext.getRowInfos().get(currentRowInfoIndex)).
+                                getColumnInfos().get(j)).
+                            setStyle(htmlDataTable.getRowGroupStyle());
+                        ((ColumnInfo)
+                            ((RowInfo)
+                                tableContext.getRowInfos().get(currentRowInfoIndex)).
+                                getColumnInfos().get(j)).
+                            setStyleClass(htmlDataTable.getRowGroupStyleClass());
+                    }
+                }
+                rowInfo.getColumnInfos().add(columnInfo);
+            }
+            if (groupEndReached) {
+                currentRowSpan = 0;
+                groupEndReached = false;
+            }
+            tableContext.getRowInfos().add(rowInfo);
+            currentRowInfoIndex++;
+        }
+
+        // do further processing if we've found at least one row
+        if (currentRowInfoIndex > -1) {
+            for (int j = 0, size = nChildren; j < size; j++) {
+                if (groupHashTable.containsKey(new Integer(j)))  // Column is groupBy
+                {
+                    ((ColumnInfo)
+                        ((RowInfo)
+                            tableContext.getRowInfos().get(currentRowInfoIndex - currentRowSpan)).
+                            getColumnInfos().get(j)).
+                        setRowSpan(currentRowSpan + 1);
+                }
+                else    // Column  is not group by
+                {
+                    ((ColumnInfo)
+                        ((RowInfo)
+                            tableContext.getRowInfos().get(currentRowInfoIndex)).
+                            getColumnInfos().get(j)).
+                        setStyle(htmlDataTable.getRowGroupStyle());
+                    ((ColumnInfo)
+                        ((RowInfo)
+                            tableContext.getRowInfos().get(currentRowInfoIndex)).
+                            getColumnInfos().get(j)).
+                        setStyleClass(htmlDataTable.getRowGroupStyleClass());
+                }
+            }
+        }
+
+        htmlDataTable.setRowIndex(-1);
+    }
+
+    protected void collectChildrenValues(List container, Iterator iterChildren) {
+        while (iterChildren.hasNext()) {
+            UIComponent child = (UIComponent) iterChildren.next();
+            if (child.isRendered()) {
+                if (child instanceof ValueHolder) {
+                    Object value = ((ValueHolder) child).getValue();
+                    container.add(value);
+                }
+
+                // we lave the column ... now iterate the facets too
+                collectChildrenValues(container, child.getFacetsAndChildren());
+            }
+        }
+    }
+
+    /**
+     * checks if the contenta of both lists are the same.<br />
+     * <b>Notice:</b> In case both lists are null or empty they are
+     * considered NOT being equal
+     */
+    protected boolean isListEqual(List list1, List list2) {
+        if (list1 == list2) {
+            return list1 != null && list1.size() > 0;
+        }
+        if (list1 == null || list2 == null || list1.size() != list2.size()) {
+            return false;
+        }
+
+        for (int i = 0; i < list1.size(); i++) {
+            Object o1 = list1.get(i);
+            Object o2 = list2.get(i);
+
+            if (o1 != null && !o1.equals(o2)) {
+                return false;
+            }
+            if (o2 != null && !o2.equals(o1)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+
+    /**
+     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#encodeEnd(javax.faces.context.FacesContext, javax.faces.component.UIComponent)
+     */
+    public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException {
+        if (uiComponent instanceof HtmlDataTable) {
+            HtmlDataTable htmlDataTable = (HtmlDataTable) uiComponent;
+            if (htmlDataTable.isRenderedIfEmpty() || htmlDataTable.getRowCount() > 0) {
+                super.encodeEnd(facesContext, uiComponent);
+            }
+        }
+        else {
+            super.encodeEnd(facesContext, uiComponent);
+        }
+    }
+
+    protected void renderRowStart(FacesContext facesContext,
+                                  ResponseWriter writer, UIData uiData, Styles styles, int rowStyleIndex)
+        throws IOException {
+        super.renderRowStart(facesContext, writer, uiData, styles, rowStyleIndex);
+
+        // get event handlers from component
+        HtmlDataTable table = (HtmlDataTable) uiData;
+
+        renderRowAttribute(writer, HTML.ONCLICK_ATTR, table.getRowOnClick());
+        renderRowAttribute(writer, HTML.ONDBLCLICK_ATTR, table.getRowOnDblClick());
+        renderRowAttribute(writer, HTML.ONKEYDOWN_ATTR, table.getRowOnKeyDown());
+        renderRowAttribute(writer, HTML.ONKEYPRESS_ATTR, table.getRowOnKeyPress());
+        renderRowAttribute(writer, HTML.ONKEYUP_ATTR, table.getRowOnKeyUp());
+        renderRowAttribute(writer, HTML.ONMOUSEDOWN_ATTR, table.getRowOnMouseDown());
+        renderRowAttribute(writer, HTML.ONMOUSEMOVE_ATTR, table.getRowOnMouseMove());
+        renderRowAttribute(writer, HTML.ONMOUSEOUT_ATTR, table.getRowOnMouseOut());
+        renderRowAttribute(writer, HTML.ONMOUSEOVER_ATTR, table.getRowOnMouseOver());
+        renderRowAttribute(writer, HTML.ONMOUSEUP_ATTR, table.getRowOnMouseUp());
+    }
+
+    /**
+     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#renderRowStyle(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIData, org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase.Styles, int)
+     */
+    protected void renderRowStyle(FacesContext facesContext, ResponseWriter writer, UIData uiData, Styles styles, int rowStyleIndex) throws IOException {
+        String rowStyleClass;
+        String rowStyle;
+        if (uiData instanceof HtmlDataTable) {
+            HtmlDataTable datatable = (HtmlDataTable) uiData;
+            rowStyleClass = datatable.getRowStyleClass();
+            rowStyle = datatable.getRowStyle();
+        }
+        else {
+            rowStyleClass = (String) uiData.getAttributes().get(JSFAttr.ROW_STYLECLASS_ATTR);
+            rowStyle = (String) uiData.getAttributes().get(JSFAttr.ROW_STYLE_ATTR);
+        }
+        if (rowStyleClass == null) {
+            super.renderRowStyle(facesContext, writer, uiData, styles, rowStyleIndex);
+        }
+        else {
+            writer.writeAttribute(HTML.CLASS_ATTR, rowStyleClass, null);
+        }
+        if (rowStyle != null) {
+            writer.writeAttribute(HTML.STYLE_ATTR, rowStyle, null);
+        }
+    }
+
+    protected void renderRowAttribute(ResponseWriter writer,
+                                      String htmlAttribute, Object value) throws IOException {
+        if (value != null) {
+            writer.writeAttribute(htmlAttribute, value, null);
+        }
+    }
+
+    /**
+     * Render the specified column object using the current row data.
+     * <p/>
+     * When the component is a UIColumn object, the inherited method is
+     * invoked to render a single table cell.
+     * <p/>
+     * In addition to the inherited functionality, support is implemented
+     * here for UIColumns children. When a UIColumns child is encountered:
+     * <pre>
+     * For each dynamic column in that UIColumns child:
+     *   * Select the column (which sets variable named by the var attribute
+     *     to refer to the current column object)
+     *   * Call this.renderColumnBody passing the UIColumns object.
+     * </pre>
+     * The renderColumnBody method eventually:
+     * <ul>
+     * <li>emits TD
+     * <li>calls encodeBegin on the UIColumns (which does nothing)
+     * <li>calls rendering methods on all children of the UIColumns
+     * <li>calls encodeEnd on the UIColumns (which does nothing)
+     * <li> emits /TD
+     * </ul>
+     * If the children of the UIColumns access the variable named by the var
+     * attribute on the UIColumns object, then they end up rendering content
+     * that is extracted from the current column object.
+     *
+     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#encodeColumnChild(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIData, javax.faces.component.UIComponent, org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase.Styles, int)
+     */
+    protected void encodeColumnChild(FacesContext facesContext,
+                                     ResponseWriter writer, UIData uiData,
+                                     UIComponent component, Styles styles, int columnStyleIndex)
+        throws IOException {
+        super.encodeColumnChild(facesContext, writer, uiData, component,
+            styles, columnStyleIndex);
+        if (component instanceof UIColumns) {
+            UIColumns columns = (UIColumns) component;
+            for (int k = 0, colSize = columns.getRowCount(); k < colSize; k++) {
+                columns.setRowIndex(k);
+                renderColumnBody(facesContext, writer, uiData, component,
+                    styles, columnStyleIndex);
+            }
+            columns.setRowIndex(-1);
+        }
+    }
+
+    /**
+     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#renderColumnBody(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIData, javax.faces.component.UIComponent, org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase.Styles, int)
+     */
+    protected void renderColumnBody(FacesContext facesContext,
+                                    ResponseWriter writer, UIData uiData,
+                                    UIComponent component, Styles styles, int columnStyleIndex)
+        throws IOException {
+        if (isGroupedTable(uiData)) {
+
+            HtmlDataTable htmlDataTable = (HtmlDataTable) uiData;
+            List tableChildren = htmlDataTable.getChildren();
+
+            int first = htmlDataTable.getFirst();
+            int rowInfoIndex = htmlDataTable.getRowIndex() - first;
+            int columnInfoIndex = tableChildren.indexOf(component);
+
+            RowInfo rowInfo = (RowInfo) htmlDataTable.getTableContext().getRowInfos().get(rowInfoIndex);
+            ColumnInfo columnInfo = (ColumnInfo) rowInfo.getColumnInfos().get(columnInfoIndex);
+
+            if (!columnInfo.isRendered()) {
+                return;
+            }
+
+            if (component instanceof HtmlColumn && amISpannedOver(null, component)) {
+                return;
+            }
+            writer.startElement(HTML.TD_ELEM, uiData);
+            String styleClass = null;
+            if (component instanceof HtmlColumn) {
+                styleClass = ((HtmlColumn) component).getStyleClass();
+            }
+            if (columnInfo.getStyleClass() != null) {
+                styleClass = columnInfo.getStyleClass();
+            }
+
+            if (styles.hasColumnStyle()) {
+                if (styleClass == null) {
+                    styleClass = styles.getColumnStyle(columnStyleIndex);
+                }
+            }
+            if (styleClass != null) {
+                writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
+            }
+
+            if (columnInfo.getStyle() != null) {
+                writer.writeAttribute(HTML.STYLE_ATTR, columnInfo.getStyle(), null);
+            }
+
+            if (columnInfo.getRowSpan() > 1) {
+                writer.writeAttribute("rowspan", new Integer(columnInfo.getRowSpan()).toString(), null);
+                if (columnInfo.getStyle() == null) {
+                    writer.writeAttribute(HTML.STYLE_ATTR, "vertical-align:top", null);
+                }
+            }
+
+            renderHtmlColumnAttributes(writer, component, null);
+
+            RendererUtils.renderChild(facesContext, component);
+            writer.endElement(HTML.TD_ELEM);
+        }
+        else if (component instanceof HtmlColumn) {
+            if (amISpannedOver(null, component)) {
+                return;
+            }
+            writer.startElement(HTML.TD_ELEM, uiData);
+            String styleClass = ((HtmlColumn) component).getStyleClass();
+            if (styles.hasColumnStyle()) {
+                if (styleClass == null) {
+                    styleClass = styles.getColumnStyle(columnStyleIndex);
+                }
+            }
+            if (styleClass != null) {
+                writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
+            }
+            renderHtmlColumnAttributes(writer, component, null);
+
+            RendererUtils.renderChild(facesContext, component);
+            writer.endElement(HTML.TD_ELEM);
+        }
+        else {
+            super.renderColumnBody(facesContext, writer, uiData, component,
+                styles, columnStyleIndex);
+        }
+    }
+
+    /**
+     * Render the header or footer of the specified column object.
+     * <p/>
+     * When the component is a UIColumn object, the inherited method is
+     * invoked to render a single header cell.
+     * <p/>
+     * In addition to the inherited functionality, support is implemented
+     * here for UIColumns children. When a UIColumns child is encountered:
+     * <pre>
+     * For each dynamic column in that UIColumns child:
+     *   * Select the column (which sets variable named by the var attribute
+     *     to refer to the current column object)
+     *   * Call this.renderColumnHeaderCell or this.renderColumnFooterCell
+     *     passing the header or footer facet of the UIColumns object.
+     * </pre>
+     * If the facet of the UIColumns accesses the variable named by the var
+     * attribute on the UIColumns object, then it ends up rendering content
+     * that is extracted from the current column object.
+     *
+     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#renderColumnChildHeaderOrFooterRow(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIComponent, java.lang.String, boolean)
+     */
+    protected void renderColumnChildHeaderOrFooterRow(
+        FacesContext facesContext, ResponseWriter writer,
+        UIComponent uiComponent, String styleClass, boolean header)
+        throws IOException {
+        super.renderColumnChildHeaderOrFooterRow(facesContext, writer,
+            uiComponent, styleClass, header);
+        if (uiComponent instanceof UIColumns) {
+            UIColumns columns = (UIColumns) uiComponent;
+            for (int i = 0, size = columns.getRowCount(); i < size; i++) {
+                columns.setRowIndex(i);
+                if (header) {
+                    renderColumnHeaderCell(facesContext, writer, columns,
+                        columns.getHeader(), styleClass, 0);
+                }
+                else {
+                    renderColumnFooterCell(facesContext, writer, columns,
+                        columns.getFooter(), styleClass, 0);
+                }
+            }
+            columns.setRowIndex(-1);
+        }
+    }
+
+    /**
+     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#renderColumnHeaderCell(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIComponent, javax.faces.component.UIComponent, java.lang.String, int)
+     */
+    protected void renderColumnHeaderCell(FacesContext facesContext,
+                                          ResponseWriter writer, UIComponent uiComponent,
+                                          UIComponent facet, String headerStyleClass, int colspan)
+        throws IOException {
+        if (uiComponent instanceof HtmlColumn) {
+
+            HtmlColumn column = (HtmlColumn) uiComponent;
+
+            if (amISpannedOver("header", uiComponent)) {
+                return;
+            }
+
+            writer.startElement(determineHeaderCellTag(facesContext, uiComponent.getParent()), uiComponent);
+
+            String columnId = column.getColumnId();
+            if (columnId != null)
+            {
+                writer.writeAttribute(HTML.ID_ATTR, columnId, null);
+            }
+
+            if (colspan > 1) {
+                writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(colspan),
+                    null);
+            }
+            String styleClass = ((HtmlColumn) uiComponent)
+                .getHeaderstyleClass();
+            if (styleClass == null) {
+                styleClass = headerStyleClass;
+            }
+            if (styleClass != null) {
+                writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
+            }
+            renderHtmlColumnAttributes(writer, uiComponent, "header");
+            if (facet != null) {
+                RendererUtils.renderChild(facesContext, facet);
+            }
+            writer.endElement(determineHeaderCellTag(facesContext, uiComponent.getParent()));
+        }
+        else {
+            super.renderColumnHeaderCell(facesContext, writer, uiComponent,
+                facet, headerStyleClass, colspan);
+        }
+    }
+
+    /**
+     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#renderColumnFooterCell(javax.faces.context.FacesContext, javax.faces.context.ResponseWriter, javax.faces.component.UIComponent, javax.faces.component.UIComponent, java.lang.String, int)
+     */
+    protected void renderColumnFooterCell(FacesContext facesContext,
+                                          ResponseWriter writer, UIComponent uiComponent,
+                                          UIComponent facet, String footerStyleClass, int colspan)
+        throws IOException {
+        if (uiComponent instanceof HtmlColumn) {
+            if (amISpannedOver("footer", uiComponent)) {
+                return;
+            }
+            writer.startElement(HTML.TD_ELEM, uiComponent);
+            if (colspan > 1) {
+                writer.writeAttribute(HTML.COLSPAN_ATTR, new Integer(colspan),
+                    null);
+            }
+            String styleClass = ((HtmlColumn) uiComponent)
+                .getFooterstyleClass();
+            if (styleClass == null) {
+                styleClass = footerStyleClass;
+            }
+            if (styleClass != null) {
+                writer.writeAttribute(HTML.CLASS_ATTR, styleClass, null);
+            }
+            renderHtmlColumnAttributes(writer, uiComponent, "footer");
+            if (facet != null) {
+                RendererUtils.renderChild(facesContext, facet);
+            }
+            writer.endElement(HTML.TD_ELEM);
+        }
+        else {
+            super.renderColumnFooterCell(facesContext, writer, uiComponent,
+                facet, footerStyleClass, colspan);
+        }
+    }
+
+    protected void renderHtmlColumnAttributes(ResponseWriter writer,
+                                              UIComponent uiComponent, String prefix) throws IOException {
+        String[] attrs = (String[]) ArrayUtils.concat(HTML.COMMON_PASSTROUGH_ATTRIBUTES_WITHOUT_STYLE, new String[]{HTML.COLSPAN_ATTR});
+        for (int i = 0, size = attrs.length; i < size; i++) {
+            String attributeName = attrs[i];
+            String compAttrName = prefix != null ? prefix + attributeName : attributeName;
+            HtmlRendererUtils.renderHTMLAttribute(writer, uiComponent,
+                compAttrName, attributeName);
+        }
+        String compAttrName = prefix != null ? prefix + HTML.STYLE_ATTR : HTML.STYLE_ATTR;
+        HtmlRendererUtils.renderHTMLAttribute(writer, uiComponent,
+            compAttrName, HTML.STYLE_ATTR);
+
+        HtmlRendererUtils.renderHTMLAttribute(writer, uiComponent,
+            HTML.WIDTH_ATTR, HTML.WIDTH_ATTR);
+    }
+
+    /**
+     * Return the number of columns spanned by the specified component.
+     * <p/>
+     * For normal components, use the inherited implementation.
+     * For UIColumns children, return the number of dynamic columns rendered
+     * by that child.
+     *
+     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase
+     *      #determineChildColSpan(javax.faces.component.UIComponent)
+     */
+    protected int determineChildColSpan(UIComponent uiComponent) {
+        int result = super.determineChildColSpan(uiComponent);
+        if (uiComponent instanceof UIColumns) {
+            result += ((UIColumns) uiComponent).getRowCount();
+        }
+        return result;
+    }
+
+    /**
+     * Return true if the specified component has a facet that needs to be
+     * rendered in a THEAD or TFOOT section.
+     *
+     * @see org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlTableRendererBase#hasFacet(boolean, javax.faces.component.UIComponent)
+     */
+    protected boolean hasFacet(boolean header, UIComponent uiComponent) {
+        boolean result = super.hasFacet(header, uiComponent);
+        if (!result && uiComponent instanceof UIColumns) {
+            // Why is this necessary? It seems to me that the inherited
+            // implementation will work fine with a UIColumns component...
+            UIColumns columns = (UIColumns) uiComponent;
+            result = header ? columns.getHeader() != null : columns.getFooter() != null;
+        }
+        return result;
+    }
+
+    /**
+     * Renders the column footer.
+     * Rendering will be supressed if all of the facets have rendered="false"
+     */
+    protected void renderColumnFooterRow(FacesContext facesContext, ResponseWriter writer, UIComponent component, String footerStyleClass) throws IOException {
+        if (determineRenderFacet(component, false)) {
+            super.renderColumnFooterRow(facesContext, writer, component, footerStyleClass);
+        }
+    }
+
+    /**
+     * Renders the column header.
+     * Rendering will be supressed if all of the facets have rendered="false"
+     */
+    protected void renderColumnHeaderRow(FacesContext facesContext, ResponseWriter writer, UIComponent component, String headerStyleClass) throws IOException {
+        if (determineRenderFacet(component, true)) {
+            super.renderColumnHeaderRow(facesContext, writer, component, headerStyleClass);
+        }
+    }
+
+    /**
+     * determine if the header or footer should be rendered.
+     */
+    protected boolean determineRenderFacet(UIComponent component, boolean header) {
+        for (Iterator it = getChildren(component).iterator(); it.hasNext();) {
+            UIComponent uiComponent = (UIComponent) it.next();
+            if (uiComponent.isRendered() && determineChildColSpan(uiComponent) > 0) {
+                UIComponent facet = header ? (UIComponent) uiComponent.getFacets().get(HEADER_FACET_NAME)
+                    : (UIComponent) uiComponent.getFacets().get(FOOTER_FACET_NAME);
+
+                if (facet != null && facet.isRendered()) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    protected void beforeColumn(FacesContext facesContext, UIData uiData, int columnIndex) throws IOException {
+        super.beforeColumn(facesContext, uiData, columnIndex);
+
+        if (uiData instanceof HtmlDataTable) {
+            HtmlDataTable dataTable = (HtmlDataTable) uiData;
+
+            putSortedReqScopeParam(facesContext, dataTable, columnIndex);
+        }
+    }
+
+    protected void beforeColumnHeaderOrFooter(FacesContext facesContext, UIData uiData, boolean header, int columnIndex) throws IOException {
+        super.beforeColumnHeaderOrFooter(facesContext, uiData, header, columnIndex);
+
+        if (header && uiData instanceof HtmlDataTable) {
+            HtmlDataTable dataTable = (HtmlDataTable) uiData;
+
+            putSortedReqScopeParam(facesContext, dataTable, columnIndex);
+        }
+    }
+
+    protected void putSortedReqScopeParam(FacesContext facesContext, HtmlDataTable dataTable, int columnIndex) {
+        String sortedColumnVar = dataTable.getSortedColumnVar();
+        Map requestMap = facesContext.getExternalContext().getRequestMap();
+
+        if (columnIndex == dataTable.getSortColumnIndex()) {
+            if (sortedColumnVar != null) {
+                requestMap.put(sortedColumnVar, Boolean.TRUE);
+            }
+        }
+        else if (sortedColumnVar != null) {
+            requestMap.remove(sortedColumnVar);
+        }
+    }
+
+    /**
+     * specify if the header, footer or <td> is spanned over (not shown) because
+     * of a colspan in a cell in a previous column
+     *
+     * @param prefix    header, footer or null
+     * @param component
+     */
+    protected boolean amISpannedOver(String prefix, UIComponent component) {
+        UIComponent table = component.getParent();
+        int span = 0;
+        for (Iterator it = table.getChildren().iterator(); it.hasNext();) {
+            UIComponent columnComponent = (UIComponent) it.next();
+            if (!(columnComponent instanceof HtmlColumn)) {
+                continue;
+            }
+            if (span > 0) {
+                span--;
+            }
+            if (columnComponent == component) {
+                return span > 0;
+            }
+            if (span == 0) {
+                try {
+                    if (prefix == null && ((HtmlColumn) columnComponent).getColspan() != null) {
+                        span = Integer.parseInt(((HtmlColumn) columnComponent).getColspan());
+                    }
+                    if ("header".equals(prefix) && ((HtmlColumn) columnComponent).getHeadercolspan() != null) {
+                        span = Integer.parseInt(((HtmlColumn) columnComponent).getHeadercolspan());
+                    }
+                    if ("footer".equals(prefix) && ((HtmlColumn) columnComponent).getFootercolspan() != null) {
+                        span = Integer.parseInt(((HtmlColumn) columnComponent).getFootercolspan());
+                    }
+                }
+                catch (NumberFormatException ex) {
+                    log.warn("Invalid " + ((prefix == null) ? "" : prefix) + "colspan attribute ignored");
+                }
+            }
+        }
+        return false;
+    }
+
+
+    /**
+     * Perform any operations necessary in the TBODY start tag.
+     *
+     * @param facesContext the <code>FacesContext</code>.
+     * @param uiData       the <code>UIData</code> being rendered.
+     */
+    protected void inBodyStart(FacesContext facesContext, UIData uiData) throws IOException {
+        String bodyStyleClass;
+        String bodyStyle;
+
+        if (uiData instanceof HtmlDataTable) {
+            bodyStyleClass = ((HtmlDataTable) uiData).getBodyStyleClass();
+            bodyStyle = ((HtmlDataTable) uiData).getBodyStyle();
+        }
+        else {
+            bodyStyleClass = (String) uiData.getAttributes().get(BODY_STYLE_CLASS);
+            bodyStyle = (String) uiData.getAttributes().get(BODY_STYLE);
+        }
+
+        ResponseWriter writer = facesContext.getResponseWriter();
+        if (bodyStyleClass != null) {
+            writer.writeAttribute(HTML.CLASS_ATTR, bodyStyleClass,
+                BODY_STYLE_CLASS);
+        }
+        if (bodyStyle != null) {
+            writer.writeAttribute(HTML.STYLE_ATTR, bodyStyle, BODY_STYLE);
+        }
+    }
+
+
+}

Propchange: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlTableRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/renderkit/html/ext/HtmlTableRenderer.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/validator/ValidatorBase.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/validator/ValidatorBase.java?rev=664402&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/validator/ValidatorBase.java (added)
+++ myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/validator/ValidatorBase.java Sat Jun  7 14:59:02 2008
@@ -0,0 +1,345 @@
+/*
+ * 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.validator;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.el.ValueExpression;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.Validator;
+
+import org.apache.myfaces.shared_tomahawk.util.MessageUtils;
+
+/**
+ * Base validator implementation for Apache MyFaces Commons Validators.
+ *
+ * @JSFValidator
+ *   configExcluded = "true"
+ *   tagClass = "org.apache.myfaces.validator.ValidatorBaseTag"
+ */
+public abstract class ValidatorBase implements StateHolder, Validator {
+
+    private String _summaryMessage = null;
+    private String _detailMessage = null;
+    private boolean _transient = false;
+
+    /**
+     *
+     * @JSFProperty
+     * @return  The summary message to be displayed
+     */
+    public String getSummaryMessage()
+    {
+        if (_summaryMessage != null) return _summaryMessage;
+        ValueExpression expression = getValueExpression("summaryMessage");
+        return expression != null ? getStringValue(getFacesContext(), expression) : null;
+    }
+
+    /**
+     *
+     * @param message   The summary message to be displayed.
+     */
+    public void setSummaryMessage(String message) {
+        _summaryMessage = message;
+    }
+
+    /**
+     *
+     * @JSFProperty
+     * @return  The message.
+     * @deprecated Use getDetailMessage()
+     */
+    public String getMessage() {
+        return getDetailMessage();
+    }
+
+    /**
+     *
+     * @param message  The detail message to be displayed.
+     * @deprecated Use setDetailMessage()
+     */
+    public void setMessage(String message) {
+        setDetailMessage(message);
+    }
+
+
+    /**
+     *
+     * @JSFProperty
+     * @return  The detail message.
+     */
+    public String getDetailMessage() {
+        if (_detailMessage != null) return _detailMessage;
+        ValueExpression vb = getValueExpression("detailMessage");
+        return vb != null ? getStringValue(getFacesContext(), vb) : null;
+    }
+
+    /**
+     *
+     * @param message  The detail message to be displayed.
+     */
+    public void setDetailMessage(String message) {
+        _detailMessage = message;
+    }
+
+
+    /**
+     * @param context
+     */
+    public Object saveState(FacesContext context) {
+        Object[] state = new Object[3];
+        state[0] = _summaryMessage;
+        state[1] = _detailMessage;
+        state[2] = saveValueExpressionMap(context);
+        return state;
+    }
+
+    public void restoreState(FacesContext context, Object state) {
+        Object[] values = (Object[]) state;
+        _summaryMessage = (String) values[0];
+        _detailMessage = (String) values[1];
+        restoreValueExpressionMap(context, values[2]);
+    }
+
+    public boolean isTransient() {
+        return _transient;
+    }
+
+    public void setTransient(boolean newTransientValue) {
+        _transient = newTransientValue;
+    }
+
+    // Utility methods
+
+    /**
+     * @param defaultMessage The default message we would expect.
+     * @param args Arguments for parsing this message.
+     * @return FacesMessage
+     */
+    protected FacesMessage getFacesMessage(String defaultMessage, Object[] args) {
+        FacesMessage msg;
+
+        if (getSummaryMessage() == null && getDetailMessage() == null)
+        {
+            msg = MessageUtils.getMessage(FacesMessage.SEVERITY_ERROR, defaultMessage, args);
+        } else {
+            Locale locale = MessageUtils.getCurrentLocale();
+            String summaryText = MessageUtils.substituteParams(locale, getSummaryMessage(), args);
+            String detailText = MessageUtils.substituteParams(locale, getDetailMessage(), args);
+            msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, summaryText, detailText);
+        }
+        return msg;
+    }
+
+    // --------------------- borrowed from UIComponentBase ------------
+
+    private Map _valueExpressionMap = null;
+
+    public ValueExpression getValueExpression(String name)
+    {
+        if (name == null) throw new NullPointerException("name");
+        if (_valueExpressionMap == null)
+        {
+            return null;
+        }
+        else
+        {
+            return (ValueExpression)_valueExpressionMap.get(name);
+        }
+    }
+
+    public void setValueExpression(String name,
+                                ValueExpression binding)
+    {
+        if (name == null) throw new NullPointerException("name");
+        if (_valueExpressionMap == null)
+        {
+            _valueExpressionMap = new HashMap();
+        }
+        _valueExpressionMap.put(name, binding);
+    }
+
+    private Object saveValueExpressionMap(FacesContext context)
+    {
+        if (_valueExpressionMap != null)
+        {
+            int initCapacity = (_valueExpressionMap.size() * 4 + 3) / 3;
+            HashMap stateMap = new HashMap(initCapacity);
+            for (Iterator it = _valueExpressionMap.entrySet().iterator(); it.hasNext(); )
+            {
+                Map.Entry entry = (Map.Entry)it.next();
+                stateMap.put(entry.getKey(),
+                             saveAttachedState(context, entry.getValue()));
+            }
+            return stateMap;
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    private void restoreValueExpressionMap(FacesContext context, Object stateObj)
+    {
+        if (stateObj != null)
+        {
+            Map stateMap = (Map)stateObj;
+            int initCapacity = (stateMap.size() * 4 + 3) / 3;
+            _valueExpressionMap = new HashMap(initCapacity);
+            for (Iterator it = stateMap.entrySet().iterator(); it.hasNext(); )
+            {
+                Map.Entry entry = (Map.Entry)it.next();
+                _valueExpressionMap.put(entry.getKey(),
+                                     restoreAttachedState(context, entry.getValue()));
+            }
+        }
+        else
+        {
+            _valueExpressionMap = null;
+        }
+    }
+
+    /**
+     * Serializes objects which are "attached" to this component but which are
+     * not UIComponent children of it. Examples are validator and listener
+     * objects. To be precise, it returns an object which implements
+     * java.io.Serializable, and which when serialized will persist the
+     * state of the provided object.
+     * <p>
+     * If the attachedObject is a List then every object in the list is saved
+     * via a call to this method, and the returned wrapper object contains
+     * a List object.
+     * <p>
+     * If the object implements StateHolder then the object's saveState is
+     * called immediately, and a wrapper is returned which contains both
+     * this saved state and the original class name. However in the case
+     * where the StateHolder.isTransient method returns true, null is
+     * returned instead.
+     * <p>
+     * If the object implements java.io.Serializable then the object is simply
+     * returned immediately; standard java serialization will later be used
+     * to store this object.
+     * <p>
+     * In all other cases, a wrapper is returned which simply stores the type
+     * of the provided object. When deserialized, a default instance of that
+     * type will be recreated.
+     */
+    public static Object saveAttachedState(FacesContext context,
+                                           Object attachedObject)
+    {
+        if (attachedObject == null) return null;
+        if (attachedObject instanceof List)
+        {
+            List lst = new ArrayList(((List)attachedObject).size());
+            for (Iterator it = ((List)attachedObject).iterator(); it.hasNext(); )
+            {
+                lst.add(saveAttachedState(context, it.next()));
+            }
+            return new AttachedListStateWrapper(lst);
+        }
+        else if (attachedObject instanceof StateHolder)
+        {
+            if (((StateHolder)attachedObject).isTransient())
+            {
+                return null;
+            }
+            else
+            {
+                return new AttachedStateWrapper(attachedObject.getClass(),
+                                                 ((StateHolder)attachedObject).saveState(context));
+            }
+        }
+        else if (attachedObject instanceof Serializable)
+        {
+            return attachedObject;
+        }
+        else
+        {
+            return new AttachedStateWrapper(attachedObject.getClass(), null);
+        }
+    }
+
+    public static Object restoreAttachedState(FacesContext context,
+                                              Object stateObj)
+            throws IllegalStateException
+    {
+        if (context == null) throw new NullPointerException("context");
+        if (stateObj == null) return null;
+        if (stateObj instanceof AttachedListStateWrapper)
+        {
+            List lst = ((AttachedListStateWrapper)stateObj).getWrappedStateList();
+            List restoredList = new ArrayList(lst.size());
+            for (Iterator it = lst.iterator(); it.hasNext(); )
+            {
+                restoredList.add(restoreAttachedState(context, it.next()));
+            }
+            return restoredList;
+        }
+        else if (stateObj instanceof AttachedStateWrapper)
+        {
+            Class clazz = ((AttachedStateWrapper)stateObj).getClazz();
+            Object restoredObject;
+            try
+            {
+                restoredObject = clazz.newInstance();
+            }
+            catch (InstantiationException e)
+            {
+                throw new RuntimeException("Could not restore StateHolder of type " + clazz.getName() + " (missing no-args constructor?)", e);
+            }
+            catch (IllegalAccessException e)
+            {
+                throw new RuntimeException(e);
+            }
+            if (restoredObject instanceof StateHolder)
+            {
+                Object wrappedState = ((AttachedStateWrapper)stateObj).getWrappedStateObject();
+                ((StateHolder)restoredObject).restoreState(context, wrappedState);
+            }
+            return restoredObject;
+        }
+        else
+        {
+            return stateObj;
+        }
+    }
+
+
+    protected FacesContext getFacesContext()
+    {
+        return FacesContext.getCurrentInstance();
+    }
+    protected String getStringValue(FacesContext context, ValueExpression vb)
+    {
+        Object value = vb.getValue(context.getELContext());
+        if (value != null)
+        {
+            return value.toString();
+        }
+        return null;
+    }
+}

Propchange: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/validator/ValidatorBase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/validator/ValidatorBase.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/validator/ValidatorBaseTag.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/validator/ValidatorBaseTag.java?rev=664402&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/validator/ValidatorBaseTag.java (added)
+++ myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/validator/ValidatorBaseTag.java Sat Jun  7 14:59:02 2008
@@ -0,0 +1,101 @@
+/*
+ * 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.validator;
+
+import javax.el.ValueExpression;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.Validator;
+import javax.faces.webapp.ValidatorELTag;
+import javax.servlet.jsp.JspException;
+
+/**
+ * ValidatorBaseTag provides support for ValidatorBase subclasses.
+ * ValidatorBaseTag subclass tld entries should include the following to pick up attribute defintions.
+ *         &ext_validator_base_attributes;
+ * 
+ * @author mkienenb (latest modification by $Author$)
+ * @version $Revision$
+ */
+public abstract class ValidatorBaseTag extends ValidatorELTag {
+    private static final long serialVersionUID = 4416508071412794682L;
+    private ValueExpression _message = null;
+    private ValueExpression _detailMessage = null;
+    private ValueExpression _summaryMessage = null;
+
+    public void setMessage(ValueExpression string) {
+        _message = string;
+    }
+
+    public void setDetailMessage(ValueExpression detailMessage)
+    {
+        _detailMessage = detailMessage;
+    }
+
+    public void setSummaryMessage(ValueExpression summaryMessage)
+    {
+        _summaryMessage = summaryMessage;
+    }
+
+    protected void _setProperties(Validator v) throws JspException {
+
+        ValidatorBase validator = (ValidatorBase) v;
+
+        FacesContext facesContext = FacesContext.getCurrentInstance();
+
+        if(_message != null && _detailMessage != null)
+            throw new JspException("you may not set detailMessage and detailMessage together - they serve the same purpose.");
+
+        ValueExpression detailMessage = _message;
+
+        if(_detailMessage != null)
+            detailMessage = _detailMessage;
+
+        if (detailMessage != null)
+        {
+            if (!_detailMessage.isLiteralText())
+            {
+                validator.setValueExpression("detailMessage",_detailMessage);
+            }
+            else
+            {
+                validator.setDetailMessage((String)_detailMessage.getValue(facesContext.getELContext()));
+            }
+        }
+
+        if (_summaryMessage != null)
+        {
+            if (!_summaryMessage.isLiteralText())
+            {
+                validator.setValueExpression("summaryMessage",_summaryMessage);
+            }
+            else
+            {
+                validator.setSummaryMessage((String)_summaryMessage.getValue(facesContext.getELContext()));
+            }
+        }
+    }
+
+    public void release()
+    {
+        super.release();
+        _message= null;
+        _detailMessage = null;
+        _summaryMessage = null;
+    }
+}

Propchange: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/validator/ValidatorBaseTag.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/tomahawk/trunk/core12/src/main/java/org/apache/myfaces/validator/ValidatorBaseTag.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL