package org.richfaces.bootstrap.component; import javax.faces.component.UIComponent; import javax.faces.component.UIComponentBase; import javax.faces.event.AbortProcessingException; import javax.faces.event.ComponentSystemEvent; import javax.faces.event.ComponentSystemEventListener; import javax.faces.event.ListenerFor; import javax.faces.event.PostAddToViewEvent; @ListenerFor(systemEventClass = PostAddToViewEvent.class) public abstract class AbstractSemanticComponent<T> extends UIComponentBase implements ComponentSystemEventListener { public abstract Class<T> getRendererCapability(); public abstract String getRendererType(T container); @Override public void processEvent(ComponentSystemEvent event) throws AbortProcessingException { Class<T> rendererCapability = getRendererCapability(); T container = findParentImplementing(rendererCapability); if (container == null) { throw new IllegalArgumentException("Semantic component must be nested within the top-level component"); } String rendererType = getRendererType(container); if (rendererType != null) { this.setRendererType(rendererType); } } @SuppressWarnings("unchecked") private T findParentImplementing(Class<T> type) { UIComponent current = this; while (current != null) { if (type.isAssignableFrom(current.getClass())) { return (T) current; } current = current.getParent(); } return null; } }