All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.jsftemplating.component.factory.ComponentFactoryBase 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 2006 Sun Microsystems, Inc. All rights reserved.
 */
package com.sun.jsftemplating.component.factory;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.el.ValueExpression;
import javax.faces.component.ActionSource;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;

import com.sun.jsftemplating.component.ComponentUtil;
import com.sun.jsftemplating.el.VariableResolver;
import com.sun.jsftemplating.layout.descriptors.LayoutComponent;
import com.sun.jsftemplating.layout.descriptors.handler.Handler;
import com.sun.jsftemplating.layout.event.CommandActionListener;
import com.sun.jsftemplating.layout.event.ValueChangeListener;
import com.sun.jsftemplating.util.LogUtil;


/**
 *  

This abstract class provides common functionality for UIComponent * factories.

* * @author Ken Paulsen ([email protected]) */ public abstract class ComponentFactoryBase implements ComponentFactory { /** *

This is the factory method responsible for creating the * UIComponent.

* * @param context The FacesContext * @param descriptor The {@link LayoutComponent} descriptor associated * with the requested UIComponent. * @param parent The parent UIComponent * * @return The newly created UIComponent. */ public abstract UIComponent create(FacesContext context, LayoutComponent descriptor, UIComponent parent); /** *

This method iterates through the Map of options. It looks at each * one, if it contians an EL expression, it sets a value binding. * Otherwise, it calls setAttribute() on the component (which in turn * will invoke the bean setter if there is one).

* *

This method also interates through the child * LayoutElements of the given {@link LayoutComponent} * descriptor and adds Facets or children as appropriate.

* * @param context The FacesContext * @param desc The {@link LayoutComponent} descriptor associated with * the requested UIComponent. * @param comp The UIComponent */ protected void setOptions(FacesContext context, LayoutComponent desc, UIComponent comp) { if (desc == null) { // Nothing to do return; } // First set the id if supplied, treated special b/c the component // used for ${} expressions is the parent and this must be set first // so other ${} expressions can use $this{id} and $this{clientId}. String compId = (String) desc.getId(context, comp.getParent()); if ((compId != null) && (!compId.equals(""))) { comp.setId(compId); } // Loop through all the options and set the values // FIXME: Figure a way to skip options that should not be set on the Component Iterator it = desc.getOptions().keySet().iterator(); String key = null; while (it.hasNext()) { // Get next property key = it.next(); setOption(context, comp, desc, key, desc.getOption(key)); } // Check for "command" handlers... List handlers = desc.getHandlers(LayoutComponent.COMMAND); if ((handlers != null) && (comp instanceof ActionSource)) { ((ActionSource) comp).addActionListener( CommandActionListener.getInstance()); } // Check for "valueChange" handlers... handlers = desc.getHandlers(ValueChangeListener.VALUE_CHANGE); if ((handlers != null) && (comp instanceof EditableValueHolder)) { ((EditableValueHolder) comp).addValueChangeListener( ValueChangeListener.getInstance()); } // Set the events on the new component storeInstanceHandlers(desc, comp); } /** *

This method sets an individual option on the * UIComponent. It will check to see if it is a * ValueExpression, if it is it will store it as * such.

*/ protected void setOption(FacesContext context, UIComponent comp, LayoutComponent desc, String key, Object value) { ComponentUtil.getInstance(context).setOption(context, key, value, desc, comp); } /** *

This method is responsible for interating over the "instance" * handlers and applying them to the UIComponent. An "instance" * handler is one that is defined outside a renderer, or a * nested component within a renderer. In other words, a handler * that would not get fired by the TemplateRenderer. By passing this * in via the UIComponent, code that is aware of events (see * {@link com.sun.jsftemplating.layout.descriptors.LayoutElementBase}) * may find these events and fire them. These may vary per "instance" * of a particular component (i.e. TreeNode) unlike the * handlers defined in a TemplateRender's XML (which are shared and * therefor should not change dynamically).

* *

This method is invoked from setOptions(), however, if setOptions * is not used in by a factory, this method may be invoked directly. * Calling this method multiple times will not cause any harm, * besides making an extra unnecessary call.

* * @param desc The descriptor potentially containing handlers to copy. * @param comp The UIComponent instance to store the handlers. */ protected void storeInstanceHandlers(LayoutComponent desc, UIComponent comp) { if (!desc.isNested()) { UIComponent parent = comp.getParent(); if ((parent == null) || (parent instanceof UIViewRoot)) { // This is not a nested LayoutComponent, it should not store // instance handlers // NOTE: could skip TemplateComponent children also. Although // this is harder to detect as dynamic children aren't // defined in the template and therefor must be stored in // the UIComponent tree. return; } } // Iterate over the instance handlers Iterator it = desc.getHandlersByTypeMap().keySet().iterator(); if (it.hasNext()) { String eventType = null; Map compAttrs = comp.getAttributes(); while (it.hasNext()) { // Assign instance handlers to attribute for retrieval later // (NOTE: retrieval must be explicit, see LayoutElementBase) eventType = it.next(); if (eventType.equals(LayoutComponent.BEFORE_CREATE)) { // This is handled directly, no need for instance handler continue; } else if (eventType.equals(LayoutComponent.AFTER_CREATE)) { // This is handled directly, no need for instance handler continue; } compAttrs.put(eventType, desc.getHandlers(eventType)); } } } /** *

This method associates the given child with the given parent. By * using this method we centralize the code so that if we decide * later to add it as a real child it can be done in one place.

* * @param context The FacesContext * @param descriptor The {@link LayoutComponent} descriptor associated * with the requested UIComponent. * @param parent The parent UIComponent * @param child The child UIComponent */ protected void addChild(FacesContext context, LayoutComponent descriptor, UIComponent parent, UIComponent child) { // Check to see if we should add this as a facet. NOTE: We add // UIViewRoot children as facets b/c we render them via the // LayoutElement tree. String facetName = descriptor.getFacetName(parent); if (facetName != null) { // Add child as a facet... if (LogUtil.configEnabled() && facetName.equals("_noname")) { // Warn the developer that they may have a problem LogUtil.config("Warning: no id was supplied for " + "component '" + child + "'!"); } // Resolve the id if its dynamic facetName = (String) ComponentUtil.getInstance(context).resolveValue( context, descriptor, child, facetName); parent.getFacets().put(facetName, child); } else { // Add this as an actual child parent.getChildren().add(child); } } /** *

This method instantiates the UIComponent given its * ComponentType. It will respect the * binding property so that a UIComponent * can be created via the binding property. While a * custom {@link ComponentFactory} can do a better job, at times it * may be desirable to use binding instead.

*/ protected UIComponent createComponent(FacesContext ctx, String componentType, LayoutComponent desc, UIComponent parent) { UIComponent comp = null; // Check for the "binding" property String binding = null; if (desc != null) { binding = (String) desc.getEvaluatedOption(ctx, "binding", parent); } if ((binding != null) && ComponentUtil.getInstance(ctx).isValueReference(binding)) { // Create a ValueExpression ValueExpression ve = ctx.getApplication().getExpressionFactory(). createValueExpression( ctx.getELContext(), binding, UIComponent.class); // Create / get the UIComponent comp = ctx.getApplication().createComponent( ve, ctx, componentType); } else { // No binding, do the normal way... comp = ctx.getApplication().createComponent(componentType); } // Parent the new component if (parent != null) { addChild(ctx, desc, parent, comp); } // Return it... return comp; } /** *

This method returns the extraInfo that was set for this * ComponentFactory from the * {@link com.sun.jsftemplating.layout.descriptors.ComponentType}.

*/ public Serializable getExtraInfo() { return _extraInfo; } /** *

This method is invoked from the * {@link com.sun.jsftemplating.layout.descriptors.ComponentType} to * provide more information to the factory. For example, if the JSF * component type was passed in, a single factory class could * instatiate multiple components the extra info that is passed in.

* *

Some factory implementations may want to override this method to * execute intialization code for the factory based in the value * passed in.

*/ public void setExtraInfo(Serializable extraInfo) { _extraInfo = extraInfo; } /** *

Extra information associated with this ComponentFactory.

*/ private Serializable _extraInfo = null; }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy