/* * � Copyright IBM Corp. 2010, 2013 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.ibm.xsp.extlib.builder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.faces.FacesException; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import com.ibm.xsp.component.FacesComponent; import com.ibm.xsp.context.FacesContextEx; import com.ibm.xsp.page.FacesComponentBuilder; import com.ibm.xsp.page.FacesPageException; import com.ibm.xsp.util.TypedUtil; public class ControlBuilder { public static UIComponent buildControl(FacesContext context, IControl control, boolean applyTheme) throws FacesException { return buildControl(context, null, null, control, applyTheme); } public static UIComponent buildControl(FacesContext context, DynamicComponentFactory factory, UIComponent parent, IControl control, boolean applyTheme) throws FacesException { // We create the component ad we add it to the parent *before* actually constructing it // This is required by some component, like UIIncludeCompiste, which look for the viewroot in // the control hierarchy. UIComponent component = control.getComponent(); if(component.getParent()==null && parent!=null) { TypedUtil.getChildren(parent).add(component); } // Ok, now we build it MainBuilder builder = new MainBuilder(factory, control, component); UIComponent c = build(context, builder); if(c!=null) { if(applyTheme) { ((FacesContextEx)context).getStyleKit().applyStyles(context, c); } } return c; } protected static UIComponent build(FacesContext context, Builder builder) throws FacesException { // Should we manage includes here, as in CompiledComponentBuilder?? UIComponent component = builder.getUIComponent(); if (component instanceof FacesComponent) { FacesComponent facesComp = (FacesComponent)component; facesComp.initBeforeContents(context); facesComp.buildContents(context, builder); facesComp.initAfterContents(context); } else { builder.buildAll(context, component, true); } return component; } /** * Wraps a JSF control. */ public static interface IControl { public String getId(); public UIComponent getComponent(); public List<IControl> getChildren(); public Map<String,IControl> getFacets(); } /** * Basic control implementation. * This implement the IControl interface. */ public static class ControlImpl<T extends UIComponent> implements IControl { private T component; private List<IControl> children; private Map<String,IControl> facets; public ControlImpl(T component) { this.component = component; } public T getComponent() { return component; } public String getId() { if(component!=null) { return component.getId(); } return null; } public List<IControl> getChildren() { return children; } public void addChild(IControl c) { if(children==null) { children = new ArrayList<IControl>(); } children.add(c); } public Map<String,IControl> getFacets() { return facets; } public void putFacet(String name, IControl c) { if(facets==null) { facets = new HashMap<String,IControl>(); } facets.put(name,c); } } /** * Custom JSF tree builder, using an hierarchy of Control objects. */ public static class Builder implements FacesComponentBuilder, DynamicComponentBuilder { private Builder parent; private IControl control; private UIComponent component; public Builder(Builder parent, IControl control, UIComponent component) { this.parent = parent; this.control = control; this.component = component; } public String getSourceComponentRef() { return parent.getSourceComponentRef(); } public Builder getParent() { return parent; } public IControl getControl() { return control; } public UIComponent getUIComponent() { return component; } public void buildAll(FacesContext context, UIComponent parent, boolean includeFacets) throws FacesPageException { // build the children of this component buildChildren(context, parent); // optionally build the facets if (includeFacets) { buildFacets(context, parent); } } public void buildChildren(FacesContext context, UIComponent parent) throws FacesPageException { List<IControl> children = control.getChildren(); if(children!=null) { UIComponent parentComponent = getUIComponent(); List<UIComponent> siblings = TypedUtil.getChildren(parentComponent); for(IControl e: children) { UIComponent childControl = e.getComponent(); if(childControl!=null) { siblings.add(childControl); Builder builder = new Builder(this,e,childControl); build(context,builder); } } } } public boolean buildFacet(FacesContext context, UIComponent parent, String facetName) throws FacesPageException { Map<String,IControl> facets = control.getFacets(); if(facets!=null) { IControl ic = facets.get(facetName); if(ic!=null) { UIComponent parentComponent = getUIComponent(); Map<String, UIComponent> siblingFacets = TypedUtil.getFacets(parentComponent); UIComponent facetComponent = ic.getComponent(); if(facetComponent!=null) { siblingFacets.put(facetName, facetComponent); Builder builder = new Builder(this,ic,facetComponent); build(context,builder); return true; } } } return false; } public void buildFacets(FacesContext context, UIComponent parent) throws FacesPageException { Map<String,IControl> facets = control.getFacets(); if(facets!=null) { UIComponent parentComponent = getUIComponent(); Map<String, UIComponent> siblingFacets = TypedUtil.getFacets(parentComponent); for(Map.Entry<String, IControl> e: facets.entrySet()) { String facetName = e.getKey(); IControl ic = e.getValue(); UIComponent facetComponent = ic.getComponent(); if(facetComponent!=null) { siblingFacets.put(facetName, facetComponent); Builder builder = new Builder(this,ic,facetComponent); build(context,builder); } } } } public boolean isFacetAvailable(FacesContext context, UIComponent parent, String facetName) { Map<String,IControl> facets = control.getFacets(); if(facets!=null) { return facets.containsKey(facetName); } return false; } } public static class MainBuilder extends Builder { private DynamicComponentFactory factory; public MainBuilder(DynamicComponentFactory factory, IControl control, UIComponent component) { super(null, control, component); this.factory = factory; } public String getSourceComponentRef() { return factory!=null ? factory.getSourceComponentRef() : null; } } }