001: package nl.knowlogy.validation.jsf.component.html;
002:
003: import java.io.IOException;
004: import java.util.List;
005:
006: import javax.faces.application.ViewHandler;
007: import javax.faces.component.UIComponent;
008: import javax.faces.component.UIViewRoot;
009: import javax.faces.context.FacesContext;
010: import javax.faces.render.Renderer;
011:
012: import nl.knowlogy.validation.jsf.utils.HTML;
013: import nl.knowlogy.validation.jsf.utils.JSFAttr;
014:
015: /**
016: */
017: public abstract class HtmlRenderer extends Renderer {
018: /**
019: * Return the list of children of the specified component.
020: * <p>
021: * This default implementation simply returns component.getChildren().
022: * However this method should always be used in order to allow renderer
023: * subclasses to override it and provide filtered or reordered views of the
024: * component children to rendering methods defined in their ancestor
025: * classes.
026: * <p>
027: * Any method that overrides this to "hide" child components should also
028: * override the getChildCount method.
029: *
030: * @return a list of UIComponent objects.
031: */
032: public List getChildren(UIComponent component) {
033: return component.getChildren();
034: }
035:
036: /**
037: * Return the number of children of the specified component.
038: * <p>
039: * See {@link #getChildren(UIComponent)} for more information.
040: */
041: public int getChildCount(UIComponent component) {
042: return component.getChildCount();
043: }
044:
045: /**
046: * @param facesContext
047: * @return String A String representing the action URL
048: */
049: protected String getActionUrl(FacesContext facesContext) {
050: ViewHandler viewHandler = facesContext.getApplication()
051: .getViewHandler();
052: String viewId = facesContext.getViewRoot().getViewId();
053: return viewHandler.getActionURL(facesContext, viewId);
054: }
055:
056: /**
057: * Renders the client ID as an "id".
058: */
059: protected void renderId(FacesContext context, UIComponent component)
060: throws IOException {
061: if (shouldRenderId(context, component)) {
062: String clientId = getClientId(context, component);
063: context.getResponseWriter().writeAttribute(HTML.ID_ATTR,
064: clientId, JSFAttr.ID_ATTR);
065: }
066: }
067:
068: /**
069: * Returns the client ID that should be used for rendering (if
070: * {@link #shouldRenderId} returns true).
071: */
072: protected String getClientId(FacesContext context,
073: UIComponent component) {
074: return component.getClientId(context);
075: }
076:
077: /**
078: * Returns true if the component should render an ID. Components that
079: * deliver events should always return "true".
080: *
081: * @todo Is this a bottleneck? If so, optimize!
082: */
083: protected boolean shouldRenderId(FacesContext context,
084: UIComponent component) {
085: String id = component.getId();
086:
087: // Otherwise, if ID isn't set, don't bother
088: if (id == null)
089: return false;
090:
091: // ... or if the ID was generated, don't bother
092: if (id.startsWith(UIViewRoot.UNIQUE_ID_PREFIX))
093: return false;
094:
095: return true;
096: }
097:
098: /**
099: * Coerces an object into a URI, accounting for JSF rules with initial
100: * slashes.
101: */
102: static public String toUri(Object o) {
103: if (o == null)
104: return null;
105:
106: String uri = o.toString();
107: if (uri.startsWith("/")) {
108: // Treat two slashes as server-relative
109: if (uri.startsWith("//")) {
110: uri = uri.substring(1);
111: } else {
112: FacesContext fContext = FacesContext
113: .getCurrentInstance();
114: uri = fContext.getExternalContext()
115: .getRequestContextPath()
116: + uri;
117: }
118: }
119:
120: return uri;
121: }
122: }
|