com.sun.jsftemplating.component.TemplateComponentHelper Maven / Gradle / Ivy
/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the license at
* https://jsftemplating.dev.java.net/cddl1.html or
* jsftemplating/cddl1.txt.
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at jsftemplating/cddl1.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* you own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
*/
package com.sun.jsftemplating.component;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
import javax.el.ValueExpression;
import com.sun.jsftemplating.layout.LayoutDefinitionException;
import com.sun.jsftemplating.layout.LayoutDefinitionManager;
import com.sun.jsftemplating.layout.descriptors.LayoutComponent;
import com.sun.jsftemplating.layout.descriptors.LayoutDefinition;
import com.sun.jsftemplating.layout.descriptors.LayoutElement;
/**
* This class provides base functionality for components that
* work in conjunction with the
* {@link com.sun.jsftemplating.renderer.TemplateRenderer}. It
* provides the bulk of the default implementation of the
* {@link TemplateComponent} interface.
*
* This class is meant to be used inside a UIComponent
class
* that implements TemplateComponent
to help provide the
* behavior of a TemplateComponent
. It is NOT an
* implementation by itself. A TemplateComonent
* implementation class may use this to help define its functionality and
* must also be an instance of UIComponent
.
*
* @see com.sun.jsftemplating.renderer.TemplateRenderer
* @see TemplateComponent
* @see TemplateComponentBase
*
* @author Ken Paulsen ([email protected])
*/
public class TemplateComponentHelper {
/**
* This class should only be used by TemplateComponent
* implementations to help them provide their
* TemplateComponent
funtionality.
*/
public TemplateComponentHelper() {
}
/**
* This method will find the request child UIComponent by id. If it
* is not found, it will attempt to create it if it can find a
* {@link LayoutElement} describing it.
*
* @param context The FacesContext
.
* @param id The UIComponent
id to find.
*
* @return The requested UIComponent
*/
public UIComponent getChild(UIComponent comp, FacesContext context, String id) {
if ((id == null) || (id.trim().equals(""))) {
// No id, no LayoutComponent, nothing we can do.
return null;
}
// We have an id, use it to search for an already-created child
// FIXME: I am doing this 2x if it falls through to create the child...
// FIXME: think about optimizing this
UIComponent childComponent = ComponentUtil.getInstance(context).findChild(comp, id, id);
if (childComponent != null) {
return childComponent;
}
// If we're still here, then we need to create it... hopefully we have
// a LayoutComponent to tell us how to do this!
LayoutDefinition ld = getLayoutDefinition(context);
if (ld == null) {
// No LayoutDefinition to tell us how to create it... return null
return null;
}
// Attempt to find a LayoutComponent matching the id
LayoutElement elt =
LayoutDefinition.getChildLayoutElementById(context, id, ld, comp);
// Create the child from the LayoutComponent
return getChild(comp, context, (LayoutComponent) elt);
}
/**
* This method will find the request child UIComponent
* by id (the id is obtained from the given {@link LayoutComponent}).
* If it is not found, it will attempt to create it from the supplied
* {@link LayoutElement}.
*
* @param descriptor The {@link LayoutElement} describing the UIComponent
.
*
* @return The requested UIComponent
*/
public UIComponent getChild(UIComponent comp, FacesContext context, LayoutComponent descriptor) {
UIComponent childComponent = null;
// Sanity check
if (descriptor == null) {
throw new IllegalArgumentException("The LayoutComponent is null!");
}
// First pull off the id from the descriptor
String id = descriptor.getId(context, comp);
ComponentUtil compUtil = ComponentUtil.getInstance(context);
if ((id != null) && !(id.trim().equals(""))) {
// We have an id, use it to search for an already-created child
childComponent = compUtil.findChild(comp, id, id);
if (childComponent != null) {
return childComponent;
}
}
// No id, or the component hasn't been created. In either case, we
// create a new component (moral: always have an id)
// Invoke "beforeCreate" handlers
descriptor.beforeCreate(context, comp);
// Create UIComponent
childComponent =
compUtil.createChildComponent(context, descriptor, comp);
// Invoke "afterCreate" handlers
descriptor.afterCreate(context, childComponent);
// Return the newly created UIComponent
return childComponent;
}
/**
* This method returns the {@link LayoutDefinition} associated with
* the UIComponent
.
*
* @param context The FacesContext
.
*
* @return {@link LayoutDefinition} associated with the UIComponent
.
*/
public LayoutDefinition getLayoutDefinition(FacesContext context) {
// Make sure we don't already have it...
if (_layoutDefinition != null) {
return _layoutDefinition;
}
// Get the LayoutDefinitionManager key
String key = getLayoutDefinitionKey();
if (key == null) {
throw new NullPointerException("LayoutDefinition key is null!");
}
// Save the LayoutDefinition for future calls to this method
try {
_layoutDefinition = LayoutDefinitionManager.
getLayoutDefinition(context, key);
} catch (LayoutDefinitionException ex) {
throw new IllegalArgumentException(
"A LayoutDefinition was not provided for '" + key
+ "'! This is required.", ex);
}
// Return the LayoutDefinition (if found)
return _layoutDefinition;
}
/**
* This method saves the state for the UIComponent
. It
* relies on the UIComponent
's superclass to save its own
* sate, and to pass in that Object
to this method.
*
* @param context The FacesContext
.
* @param superState The UIComponent
's superclass state.
*
* @return The serialized State.
*/
public Object saveState(FacesContext context, Object superState) {
Object[] values = new Object[2];
values[0] = superState;
values[1] = _ldmKey;
return values;
}
/**
* This method restores the state for the UIComponent
.
* It will return an Object
that must be passed to the
* superclass's restoreState
method.
*
* @param context The FacesContext
.
* @param state The serialized state.
*
* @return The State for the superclass to deserialize.
*/
public Object restoreState(FacesContext context, Object state) {
Object[] values = (Object[]) state;
_ldmKey = (java.lang.String) values[1];
return values[0];
}
/**
* This method returns the {@link LayoutDefinition} key for the
* UIComponent
.
*
* @return key The key to use in the {@link LayoutDefinitionManager}.
*/
public String getLayoutDefinitionKey() {
return _ldmKey;
}
/**
* This method sets the LayoutDefinition key for the
* UIComponent
.
*
* @param key The key to use in the {@link LayoutDefinitionManager}.
*/
public void setLayoutDefinitionKey(String key) {
_ldmKey = key;
}
public V getAttributeValue(UIComponent comp, V field, String attributeName, V defaultValue) {
if (field != null) {
return field;
}
ValueExpression ve = comp.getValueExpression(attributeName);
return (ve != null) ? (V) ve.getValue(FacesContext.getCurrentInstance().getELContext()) :
defaultValue;
}
/**
* This is the LayoutDefinition key for the UIComponent
.
* This is typically set by the Tag. The Component may also provide
* a default by setting it in its constructor.
*/
private String _ldmKey = null;
/**
* This is a cached reference to the {@link LayoutDefinition} used by
* the UIComponent
.
*/
private transient LayoutDefinition _layoutDefinition = null;
}