package org.jboss.seam.ui.renderkit;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.jboss.seam.contexts.Context;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.ui.component.UIDecorate;
import org.jboss.seam.ui.util.Decoration;
import org.jboss.seam.ui.util.HTML;
import org.jboss.seam.ui.util.cdk.RendererBase;
import org.richfaces.cdk.annotations.JsfRenderer;
@JsfRenderer(type="org.jboss.seam.ui.DecorateRenderer", family="org.jboss.seam.ui.DecorateRenderer")
public class DecorateRendererBase extends RendererBase
{
// Place the attributes you want to store away
private Map<String, Object> originalValues = new HashMap();
// The list of attributes in the event scope to store away
String[] storeOriginals = new String[] {"invalid", "required"};
@Override
protected Class getComponentClass()
{
return UIDecorate.class;
}
/**
* Store away the attribute from the event context (if it is set)
*
* @param names The list of context keys to store away
* @param context The context to target
*/
private void storeOriginalValues(String[] names, Context context)
{
for (String name : names)
{
if (context.isSet(name))
{
originalValues.put(name, context.get(name));
}
}
}
/**
* Restores the state of the event context. If the value is stored away, it is restored
* It it was not in the map, it was not in the context in the first place so clean
* up what we have placed there during this run.
*
* @param names The list of context keys to restore
* @param context The context to target
*/
private void restoreOriginalValues(String[] names, Context context) {
for (String name : names) {
if (originalValues.containsKey(name)) {
context.set(name, originalValues.get(name));
} else {
context.remove(name);
}
}
}
@Override
protected void doEncodeBegin(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException
{
UIDecorate decorate = (UIDecorate) component;
storeOriginalValues(storeOriginals, Contexts.getEventContext());
Contexts.getEventContext().set("invalid", Decoration.hasMessage(decorate, context));
Contexts.getEventContext().set("required", Decoration.hasRequired(component, context));
boolean hasMessage = decorate.hasMessage();
if (decorate.isEnclose())
{
writer.startElement(decorate.getElement(), decorate);
if (decorate.getStyleClass() != null)
{
writer.writeAttribute(HTML.CLASS_ATTR, decorate.getStyleClass(), HTML.CLASS_ATTR);
}
if (decorate.getStyle() != null)
{
writer.writeAttribute(HTML.STYLE_ATTR, decorate.getStyle(), HTML.STYLE_ATTR);
}
writer.writeAttribute("id", decorate.getClientId(context), "id");
}
UIComponent aroundDecoration = decorate.getDecoration("aroundField");
UIComponent aroundInvalidDecoration = decorate.getDecoration("aroundInvalidField");
if (aroundDecoration != null && !hasMessage)
{
aroundDecoration.setParent(decorate);
aroundDecoration.encodeBegin(context);
}
if (aroundInvalidDecoration != null && hasMessage)
{
aroundInvalidDecoration.setParent(decorate);
aroundInvalidDecoration.encodeBegin(context);
}
}
@Override
protected void doEncodeEnd(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException
{
UIDecorate decorate = (UIDecorate) component;
boolean hasMessage = decorate.hasMessage();
UIComponent aroundDecoration = decorate.getDecoration("aroundField");
UIComponent aroundInvalidDecoration = decorate.getDecoration("aroundInvalidField");
if (aroundDecoration != null && !hasMessage)
{
aroundDecoration.setParent(decorate);
aroundDecoration.encodeEnd(context);
}
if (aroundInvalidDecoration != null && hasMessage)
{
aroundInvalidDecoration.setParent(decorate);
aroundInvalidDecoration.encodeEnd(context);
}
if (decorate.isEnclose())
{
context.getResponseWriter().endElement(decorate.getElement());
}
restoreOriginalValues(storeOriginals, Contexts.getEventContext());
}
@Override
protected void doEncodeChildren(ResponseWriter writer, FacesContext context, UIComponent component) throws IOException
{
UIDecorate decorate = (UIDecorate) component;
boolean hasMessage = decorate.hasMessage();
UIComponent beforeDecoration = decorate.getDecoration("beforeField");
UIComponent beforeInvalidDecoration = decorate.getDecoration("beforeInvalidField");
if (beforeDecoration != null && !hasMessage)
{
beforeDecoration.setParent(decorate);
renderChild(context, beforeDecoration);
}
if (beforeInvalidDecoration != null && hasMessage)
{
beforeInvalidDecoration.setParent(decorate);
renderChild(context, beforeInvalidDecoration);
}
renderChildren(context, decorate);
UIComponent afterDecoration = decorate.getDecoration("afterField");
UIComponent afterInvalidDecoration = decorate.getDecoration("afterInvalidField");
if (afterDecoration != null && !hasMessage)
{
afterDecoration.setParent(decorate);
renderChild(context, afterDecoration);
}
if (afterInvalidDecoration != null && hasMessage)
{
afterInvalidDecoration.setParent(decorate);
renderChild(context, afterInvalidDecoration);
}
}
@Override
public boolean getRendersChildren()
{
return true;
}
}