/* * 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 2008 Sun Microsystems, Inc. All rights reserved. */ package com.sun.jsftemplating.layout; import com.sun.jsftemplating.component.ComponentUtil; import com.sun.jsftemplating.layout.descriptors.LayoutComponent; import com.sun.jsftemplating.layout.descriptors.LayoutDefinition; import com.sun.jsftemplating.layout.descriptors.LayoutElement; import java.io.IOException; import java.util.Map; import javax.faces.component.UIComponent; import javax.faces.component.UIViewRoot; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; /** *
This is a UIViewRoot implemenation that allows the
* UIComponent tree to be defined by a
* {@link LayoutDefinition}. This implementation is used by the
* {@link LayoutViewHandler} implementation in this same package. It is
* expected that {@link #setLayoutDefinitionKey(String)} will be invoked
* soon after creation. This key will be resolved by the configured
* {@link LayoutDefinitionManager} to locate the {@link LayoutDefinition}
* which defines the UIComponent tree.
Constructor.
*/ private ViewRootUtil() { } /** // FIXME: This method was originally from the LayoutViewRoot class (which // FIXME: extended UIViewRoot). This method allowed "decode" events to work // FIXME: on pages. I still need to replace this functionality w/o extending // FIXME: the UIViewRoot (if possible). *This method enables the decode event to work for pages.
* *This method checks for Ajax requests and treats them differently * than normal requests. It only decodes the targeted UIComponent * (and its children), then invokes processApplication(), and finally * renders a partial response (rendering change is actually handled * by LayoutViewHandler).
* *When decoding template-based components, this is handled by the * TemplateRenderer. However, when dealing with pages, this is done * here (TemplateRenderer is not involved to fire handlers).
* *This method continues to delegate to the superclass after invoking * any registered handlers.
public void processDecodes(FacesContext context) { // PartialTraversalViewRootHelper may call us in an attempt to call // super.processDecodes(), detect this... if (!(new RuntimeException().getStackTrace()[1].getClassName().equals(HELPER_NAME)) && !helper.processDecodes(context)) { // Request already handled... return; } // BEGIN EXPERIMENTAL CODE... ExternalContext extCtx = context.getExternalContext(); String targetId = extCtx.getRequestParameterMap().get(LayoutViewHandler.AJAX_REQ_KEY); if ((targetId != null) && !targetId.equals("")) { // Detected Ajax Request // This request will only process a sub-tree of the UIComponent // tree and return the cooresponding partial HTML // First find the Ajax target UIComponent target = findComponent(":"+targetId); if (target == null) { // FIXME: Log a warning message! // FIXME: Rework this so that the following 6 lines are duplicated LayoutDefinition def = getLayoutDefinition(context); if (def != null) { def.decode(context, this); } super.processDecodes(context); return; } extCtx.getRequestMap().put(LayoutViewHandler.AJAX_REQ_TARGET_KEY, target); // Process sub-tree (similar to immedate, no validation/update) target.processDecodes(context); processApplication(context); // Mark the context that the next phase should be RenderResponse context.renderResponse(); } else { // END EXPERIMENTAL CODE... LayoutDefinition def = getLayoutDefinition(context); if (def != null) { def.decode(context, this); } super.processDecodes(context); } } */ /** * This method provides the ability to obtain a "child"
* UIComponent from this UIViewRoot.
FacesContext.
* @param id The id of UIComponent child.
*
* @return The requested UIComponent or null if not found.
public UIComponent getChild(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
UIComponent childComponent = ComponentUtil.findChild(this, 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, this);
// Create the child from the LayoutComponent
return getChild(context, (LayoutComponent) elt);
}
*/
/**
* This method provides the ability to obtain a "child"
* UIComponent from this UIViewRoot. If
* the child does not already exist, it will be created using the
* given {@link LayoutComponent} descriptor.
FacesContext.
* @param descriptor The {@link LayoutComponent} for the
* UIComponent child.
*
* @return The requested UIComponent.
*
* @throws IllegalArgumentException if descriptor is null.
public UIComponent getChild(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, this);
if ((id != null) && !(id.trim().equals(""))) {
// We have an id, use it to search for an already-created child
childComponent = ComponentUtil.findChild(this, 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, this);
// Create UIComponent
childComponent =
ComponentUtil.createChildComponent(context, descriptor, this);
// Invoke "afterCreate" handlers
descriptor.afterCreate(context, childComponent);
// Return the newly created UIComponent
return childComponent;
}
*/
// FIXME: Documentation...
/**
* Returns the {@link LayoutDefinition}. If the * {@link LayoutDefinition} has not already be retrieved, it will be * found using the set {@link LayoutDefinition} "key". If the key is * not yet set, this method will return null.
* * @param context TheFacesContext.
*
* @return The {@link LayoutDefinition} for this UIViewRoot.
*/
public static LayoutDefinition getLayoutDefinition(UIViewRoot root) throws LayoutDefinitionException {
if (root == null) {
// Default to the current UIViewRoot
root = FacesContext.getCurrentInstance().getViewRoot();
}
return (root == null) ? null : getLayoutDefinition((String)
getLayoutDefinitionKey(root));
}
// FIXME: Documentation...
/**
*
*/
public static LayoutDefinition getLayoutDefinition(String key) throws LayoutDefinitionException {
// Make sure the key is not null
if (key == null) {
return null;
}
// Get the FacesContext
FacesContext context = FacesContext.getCurrentInstance();
// Make sure we don't already have it...
Map This method gets the {@link LayoutDefinition} key from the given
* UIViewRoot.
This method sets the {@link LayoutDefinition} key on the given
* UIViewRoot.
This is the key to be used to store the {@link LayoutDefinition}
* on the ViewRoot in its attribute map.