com.sun.jsftemplating.layout.ViewRootUtil 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 2008 Sun Microsystems, Inc. All rights reserved.
*/
package com.sun.jsftemplating.layout;
import com.sun.jsftemplating.layout.descriptors.LayoutDefinition;
import java.util.Map;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
/**
* This class provides utility methods used by JSFT for working with
* UIViewRoot
instances. JSFTemplating no longer provides
* its own UIViewRoot
, in an effort to make integration
* with other frameworks more simple. The methods in this class perform
* operations such as setting the {@link LayoutDefinition} key on the
* UIViewRoot
as an attribute. It also allows you go obtain
* the {@link LayoutDefinition} used by a specific instance of the
* UIViewRoot
, or the current instance set in the
* FacesContext
.
*
* @author Ken Paulsen ([email protected])
*/
public class ViewRootUtil {
/**
* Constructor. All methods are static, no need to instantiate this
* class.
*/
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
.
*
* @param context The 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.getInstance(context).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.
*
* @param context The 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.getInstance(context).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.getInstance(context).createChildComponent(context, descriptor, this);
// Invoke "afterCreate" handlers
descriptor.afterCreate(context, childComponent);
// Return the newly created UIComponent
return childComponent;
}
*/
/**
* Returns the {@link LayoutDefinition} used by the given
* UIViewRoot
. This method retrieves the
* {@link LayoutDefinition} key from the given UIViewRoot
* (or gets the current UIViewRoot
from the
* FacesContext
if the value passed in is
* null
. It then invokes the overloaded method
* ({@link #getLayoutDefinition(String)}) with this key.
*
* @param root The UIViewRoot
to use.
*
* @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));
}
/**
* This method returns the {@link LayoutDefinition} for the given
* key
. If the {@link LayoutDefinition} has already be
* retrieved during this request, it will be returned. Otherwise, it
* will ask the {@link LayoutDefinitionManager}.
*/
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 requestMap =
context.getExternalContext().getRequestMap();
LayoutDefinition ld = (LayoutDefinition)
requestMap.get(LAYOUT_DEFINITION_KEY + key);
if (ld != null) {
return ld;
}
// Find it...
ld = LayoutDefinitionManager.getLayoutDefinition(context, key);
// Save the LayoutDefinition for future calls to this method
requestMap.put(LAYOUT_DEFINITION_KEY + key, ld);
// Return the LayoutDefinition (if found)
return ld;
}
/**
* This method gets the {@link LayoutDefinition} key from the given
* UIViewRoot
.
*/
public static String getLayoutDefinitionKey(UIViewRoot root) {
return (String) root.getAttributes().get(LAYOUT_DEFINITION_KEY);
}
/**
* This method sets the {@link LayoutDefinition} key on the given
* UIViewRoot
.
*/
public static void setLayoutDefinitionKey(UIViewRoot root, String key) {
root.getAttributes().put(LAYOUT_DEFINITION_KEY, key);
}
/**
* This is the key to be used to store the {@link LayoutDefinition}
* on the ViewRoot
in its attribute map.
*/
public static final String LAYOUT_DEFINITION_KEY = "_ldKey";
}