in tomee you can also use mojarra but I'd just keep my component portable with myfaces if possible Romain Manni-Bucau Twitter: @rmannibucau Blog: http://rmannibucau.wordpress.com/ LinkedIn: http://fr.linkedin.com/in/rmannibucau Github: https://github.com/rmannibucau
2014-02-13 13:23 GMT+01:00 Thomas Andraschko <andraschko.tho...@gmail.com>: > I don't think that anyone will port your complete code and give you a > complete solution ;) > > The biggest problem is AFAIR that the renderer implementations are not in > the API packages. So you have to rebuild all this functionality without > dependencies to the Impl. > > e.g. > Attribute,AttributeManager -> String[] with attribute namens > Move all the utils functions to your own code (Util.componentIsDisabled, > RenderKitUtils.getSelectItems. etc.) > > The most code doesn't really depent on the IMPL code. > > > 2014-02-13 12:44 GMT+01:00 Rene Perschon <chummer_r...@gmx.net>: > >> Hi everyone! >> >> I'm currently migrating an application from Glassfish 3.1.1 to TomEE. Now >> the problem is that this application contains a custom component which was >> unfortunately coded with hard dependencies on com.sun.faces classes (maven >> dependency jsf-impl). >> >> Now my question is how can i port this component in such a way that it is >> independent from any concrete JSF implementation (or at least in such a way >> that it works with MyFaces). >> >> Here's the component: >> >> import java.io.IOException; >> import java.util.Iterator; >> import java.util.Map; >> >> import javax.faces.component.UIComponent; >> import javax.faces.component.UINamingContainer; >> import javax.faces.component.ValueHolder; >> 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 com.sun.faces.renderkit.Attribute; >> import com.sun.faces.renderkit.AttributeManager; >> import com.sun.faces.renderkit.RenderKitUtils; >> import com.sun.faces.renderkit.html_basic.MenuRenderer; >> import com.sun.faces.util.RequestStateManager; >> import com.sun.faces.util.Util; >> >> /** >> * {@inheritDoc}. >> */ >> public class CustomSelectManyCheckboxListRenderer extends MenuRenderer >> { >> /** {@inheritDoc}. */ >> private static final Attribute[] ATTRIBUTES = >> AttributeManager.getAttributes(AttributeManager.Key.SELECTMANYCHECKBOX); >> /** Representing the border string. */ >> private static final String BORDER = "border"; >> /** Representing the tr string. */ >> private static final String TR = "tr"; >> /** Representing the td string. */ >> private static final String TD = "td"; >> /** Representing the label string. */ >> private static final String LABEL = "label"; >> /** Representing the newline string. */ >> private static final String NEWLINE = "\n"; >> /** Representing the tab string. */ >> private static final String TAB = "\t"; >> /** Representing the class string. */ >> private static final String CLASS = "class"; >> /** Representing the style string. */ >> private static final String STYLE = "style"; >> /** Representing the valign string. */ >> private static final String VALIGN = "valign"; >> >> >> // ---------------------------------------------------------- Public >> Methods >> >> >> @Override >> public void encodeEnd(FacesContext context, UIComponent component) >> throws IOException >> { >> >> rendererParamsNotNull(context, component); >> >> if (!shouldEncode(component)) >> { >> return; >> } >> >> ResponseWriter writer = context.getResponseWriter(); >> assert (writer != null); >> >> String alignStr; >> Object borderObj; >> boolean alignVertical = false; >> int border = 0; >> >> >> >> if (null != component.getAttributes().get("layout")) >> { >> alignStr = (String) component.getAttributes().get("layout"); >> alignVertical = alignStr.equalsIgnoreCase("pageDirection"); >> } >> >> if (null != component.getAttributes().get(BORDER)) >> { >> borderObj = component.getAttributes().get(BORDER); >> border = (Integer) borderObj; >> } >> >> Converter converter = null; >> if (component instanceof ValueHolder) >> { >> converter = ((ValueHolder)component).getConverter(); >> } >> >> renderBeginText(component, border, alignVertical, context, true); >> >> Iterator<SelectItem> items = >> RenderKitUtils.getSelectItems(context, component); >> >> Object currentSelections = getCurrentSelectedValues(component); >> Object[] submittedValues = getSubmittedSelectedValues(component); >> Map<String, Object> attributes = component.getAttributes(); >> OptionComponentInfo optionInfo = >> new OptionComponentInfo((String) >> attributes.get("disabledClass"), >> (String) >> attributes.get("enabledClass"), >> (String) >> attributes.get("unselectedClass"), >> (String) >> attributes.get("selectedClass"), >> Util.componentIsDisabled(component), >> isHideNoSelection(component)); >> int idx = -1; >> while (items.hasNext()) >> { >> SelectItem curItem = items.next(); >> idx++; >> // If we come across a group of options, render them as a >> nested >> // table. >> if (curItem instanceof SelectItemGroup) >> { >> // write out the label for the group. >> if (curItem.getLabel() != null) >> { >> if (alignVertical) >> { >> writer.startElement(TR, component); >> } >> writer.startElement(TD, component); >> writer.writeText(curItem.getLabel(), component, LABEL); >> writer.endElement(TD); >> if (alignVertical) >> { >> writer.endElement(TR); >> } >> >> } >> if (alignVertical) >> { >> writer.startElement(TR, component); >> } >> writer.startElement(TD, component); >> writer.writeText(NEWLINE, component, null); >> renderBeginText(component, 0, alignVertical, >> context, false); >> // render options of this group. >> SelectItem[] itemsArray = >> ((SelectItemGroup) curItem).getSelectItems(); >> for (int i = 0; i < itemsArray.length; ++i) >> { >> renderOption(context, >> component, >> converter, >> itemsArray[i], >> currentSelections, >> submittedValues, >> alignVertical, >> i, >> optionInfo); >> } >> renderEndText(component, alignVertical, context); >> writer.endElement(TD); >> if (alignVertical) >> { >> writer.endElement(TR); >> writer.writeText(NEWLINE, component, null); >> } >> } >> else >> { >> renderOption(context, >> component, >> converter, >> curItem, >> currentSelections, >> submittedValues, >> alignVertical, >> idx, >> optionInfo); >> } >> } >> >> renderEndText(component, alignVertical, context); >> >> } >> >> // ------------------------------------------------------- Protected >> Methods >> >> >> /** >> * {@inheritDoc} >> */ >> @Override >> protected boolean isBehaviorSource(FacesContext ctx, >> String behaviorSourceId, >> String componentClientId) >> { >> >> if (behaviorSourceId == null) >> { >> return false; >> } >> char sepChar = UINamingContainer.getSeparatorChar(ctx); >> String actualBehaviorId = >> behaviorSourceId.substring(0, >> behaviorSourceId.lastIndexOf(sepChar)); >> return (actualBehaviorId.equals(componentClientId)); >> >> } >> >> /** >> * {@inheritDoc} >> */ >> protected void renderBeginText(UIComponent component, int border, >> boolean alignVertical, FacesContext >> context, >> boolean outerTable) throws IOException >> { >> ResponseWriter writer = context.getResponseWriter(); >> assert (writer != null); >> >> writer.startElement("table", component); >> if (border != Integer.MIN_VALUE) >> { >> writer.writeAttribute(BORDER, border, BORDER); >> } >> >> // render style and styleclass attribute on the outer table >> instead of >> // rendering it as pass through attribute on every option in the >> list. >> if (outerTable) >> { >> // render "id" only for outerTable. >> if (shouldWriteIdAttribute(component)) >> { >> writeIdAttributeIfNecessary(context, writer, component); >> } >> String styleClass = (String) component.getAttributes().get( >> "styleClass"); >> String style = (String) component.getAttributes().get(STYLE); >> if (styleClass != null) >> { >> writer.writeAttribute(CLASS, styleClass, CLASS); >> } >> if (style != null) >> { >> writer.writeAttribute(STYLE, style, STYLE); >> } >> } >> writer.writeText(NEWLINE, component, null); >> >> if (!alignVertical) >> { >> writer.writeText(TAB, component, null); >> writer.startElement(TR, component); >> writer.writeText(NEWLINE, component, null); >> } >> >> } >> >> /** >> * {@inheritDoc} >> */ >> protected void renderEndText(UIComponent component, >> boolean alignVertical, >> FacesContext context) throws IOException >> { >> >> ResponseWriter writer = context.getResponseWriter(); >> assert (writer != null); >> >> if (!alignVertical) >> { >> writer.writeText(TAB, component, null); >> writer.endElement(TR); >> writer.writeText(NEWLINE, component, null); >> } >> writer.endElement("table"); >> >> } >> >> /** >> * {@inheritDoc} >> */ >> protected void renderOption(FacesContext context, >> UIComponent component, >> Converter converter, >> SelectItem curItem, >> Object currentSelections, >> Object[] submittedValues, >> boolean alignVertical, >> int itemNumber, >> OptionComponentInfo optionInfo) throws >> IOException >> { >> >> String valueString = getFormattedValue(context, component, >> curItem.getValue(), >> converter); >> >> Object valuesArray; >> Object itemValue; >> if (submittedValues != null) >> { >> valuesArray = submittedValues; >> itemValue = valueString; >> } >> else >> { >> valuesArray = currentSelections; >> itemValue = curItem.getValue(); >> } >> >> RequestStateManager.set(context, >> >> RequestStateManager.TARGET_COMPONENT_ATTRIBUTE_NAME, >> component); >> >> boolean isSelected = isSelected(context, component, itemValue, >> valuesArray, converter); >> if (optionInfo.isHideNoSelection() && >> curItem.isNoSelectionOption() && >> currentSelections != null && >> !isSelected) >> { >> return; >> } >> >> ResponseWriter writer = context.getResponseWriter(); >> assert (writer != null); >> >> if (alignVertical) >> { >> writer.writeText(TAB, component, null); >> writer.startElement(TR, component); >> writer.writeText(NEWLINE, component, null); >> } >> writer.startElement(TD, component); >> writer.writeAttribute(VALIGN, "top", VALIGN); >> writer.writeText(NEWLINE, component, null); >> >> writer.startElement("input", component); >> writer.writeAttribute("name", component.getClientId(context), >> "clientId"); >> String idString = component.getClientId(context) + >> UINamingContainer.getSeparatorChar(context) + >> Integer.toString(itemNumber); >> writer.writeAttribute("id", idString, "id"); >> >> writer.writeAttribute("value", valueString, "value"); >> writer.writeAttribute("type", "checkbox", null); >> >> if (isSelected) >> { >> writer.writeAttribute(getSelectedTextString(), Boolean.TRUE, >> null); >> } >> >> // Don't render the disabled attribute twice if the 'parent' >> // component is already marked disabled. >> if (!optionInfo.isDisabled()) >> { >> if (curItem.isDisabled()) >> { >> writer.writeAttribute("disabled", true, "disabled"); >> } >> } >> >> // Apply HTML 4.x attributes specified on UISelectMany component >> to all >> // items in the list except styleClass and style which are >> rendered as >> // attributes of outer most table. >> RenderKitUtils.renderPassThruAttributes(context, >> writer, >> component, >> ATTRIBUTES, >> >> getNonOnClickSelectBehaviors(component)); >> >> RenderKitUtils.renderXHTMLStyleBooleanAttributes(writer, >> component); >> >> RenderKitUtils.renderSelectOnclick(context, component, true); >> >> writer.endElement("input"); >> >> //-------------------------------------------------------- >> // New stuff for event selecting >> //-------------------------------------------------------- >> >> writer.endElement(TD); >> >> // starting the label td >> writer.startElement(TD, component); >> writer.writeAttribute(VALIGN, "top", VALIGN); >> writer.writeAttribute("width", "80px", "width"); >> writer.writeAttribute(STYLE, "padding-top:4px", STYLE); >> >> String itemLabel = curItem.getLabel(); >> if (itemLabel == null) >> { >> itemLabel = valueString; >> } >> >> writer.writeText(" ", component, null); >> writer.startElement(LABEL, component); >> writer.writeAttribute("for", component.getClientId() + ":" + >> itemNumber, "for"); >> if (!curItem.isEscape()) >> { >> // It seems the ResponseWriter API should >> // have a writeText() with a boolean property >> // to determine if it content written should >> // be escaped or not. >> writer.write(itemLabel); >> } >> else >> { >> writer.writeText(itemLabel, component, null); >> } >> writer.endElement(LABEL); >> >> isSelected(context, component, itemValue, valuesArray, converter); >> // if (isSelected(context, component, itemValue, valuesArray, >> converter)) >> // { >> // // selected >> // } >> // else >> // { >> // // not selected >> // } >> writer.endElement(TD); >> >> // starting the description td >> writer.startElement(TD, component); >> writer.writeAttribute(VALIGN, "top", VALIGN); >> writer.writeAttribute(STYLE, "padding-top:4px", STYLE); >> >> String itemLabelDesc = curItem.getDescription(); >> if (itemLabelDesc == null) >> { >> itemLabelDesc = ""; >> } >> writer.writeText(" ", component, null); >> if (!curItem.isEscape()) >> { >> // It seems the ResponseWriter API should >> // have a writeText() with a boolean property >> // to determine if it content written should >> // be escaped or not. >> writer.write(itemLabelDesc); >> } >> else >> { >> writer.writeText(itemLabelDesc, component, null); >> } >> >> writer.endElement(TD); >> >> //-------------------------------------------------------- >> // New stuff for event selecting end >> //-------------------------------------------------------- >> >> writer.writeText(NEWLINE, component, null); >> if (alignVertical) >> { >> writer.writeText(TAB, component, null); >> writer.endElement(TR); >> writer.writeText(NEWLINE, component, null); >> } >> } >> >> >> // ------------------------------------------------- Package Private >> Methods >> >> /** >> * {@inheritDoc} >> */ >> String getSelectedTextString() >> { >> return "checked"; >> } >> } >> >> >> Any help is appreciated! >> Thanks! >> >> René >>