Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.horus.hflow.web.commons.tag;
- import java.io.IOException;
- import javax.el.ELException;
- import javax.el.ValueExpression;
- import javax.faces.FacesException;
- import javax.faces.component.UIComponent;
- import javax.faces.view.facelets.*;
- import com.horus.hflow.web.commons.component.DynamicInclude;
- public final class DynamicIncludeHandler extends ComponentHandler {
- public DynamicIncludeHandler(ComponentConfig config) {
- super(config);
- }
- public void onComponentCreated(FaceletContext ctx, UIComponent component, UIComponent parent) {
- DynamicInclude di = (DynamicInclude) component;
- di.setFaceletContext(ctx);
- TagAttribute[] vars = tag.getAttributes().getAll();
- for (TagAttribute var : vars) {
- String name = var.getQName();
- String value = var.getValue();
- final ValueExpression valueExpression =
- ctx.getExpressionFactory().createValueExpression(
- ctx.getFacesContext().getELContext(), value, Object.class);
- di.addValueExpression(name, valueExpression);
- }
- }
- public boolean apply(FaceletContext ctx, UIComponent parent, String name)
- throws IOException, FacesException, ELException {
- if (name == null) {
- this.nextHandler.apply(ctx, parent);
- return true;
- }
- return false;
- }
- }
- package com.horus.hflow.web.commons.component;
- import com.sun.faces.context.StateContext;
- import javax.el.ValueExpression;
- import javax.faces.component.*;
- import javax.faces.context.FacesContext;
- import javax.faces.view.facelets.FaceletContext;
- import java.io.IOException;
- import java.util.*;
- /**
- * This component allows including facelets dynamically. It is using
- * preserved FaceletContext to build component trees based on the view path.
- * This FaceletContext is enriched with attributes passed to the
- * dynamicInclude tag.
- *
- * Initially subtrees are built in the rendering phase. Then on postback
- * request they are rebuilt in restoreView phase.
- */
- public class DynamicInclude extends UIComponentBase {
- private static final String SRC_ATTRIBUTE = "src";
- private Map<String, ValueExpression> valueExpressions = Collections.emptyMap();
- private List<String> renderedSources = new ArrayList<String>();
- private List<String> restoredSources = Collections.emptyList();
- // for ajax requests this will stay false
- private boolean wasRendered = false;
- private boolean wasPurged = false;
- private FaceletContext faceletContext;
- private String src;
- public DynamicInclude() {}
- public void addValueExpression(String key, ValueExpression valueExpression) {
- if (valueExpressions == Collections.EMPTY_MAP)
- valueExpressions = new HashMap<String, ValueExpression>();
- valueExpressions.put(key, valueExpression);
- }
- @SuppressWarnings("unchecked")
- @Override
- public void encodeBegin(FacesContext context) throws IOException {
- wasRendered = true;
- if (isRendered()) {
- String src = getSrc();
- if (!renderedSources.contains(src))
- // As soon as we detect the first inconsistency between restored and
- // rendered views, we purge restored views. Otherwise we reuse restored
- // view and mark is as rendered.
- if (restoredSources.indexOf(src) == renderedSources.size())
- renderedSources.add(src);
- else if (!wasPurged)
- purgeRestoredChildren(context);
- if (!renderedSources.contains(src)) {
- buildView(context, src);
- renderedSources.add(src);
- }
- }
- }
- /**
- * Remove all restored views except those marked as rendered.
- */
- private void purgeRestoredChildren(FacesContext context) {
- StateContext stateContext = StateContext.getStateContext(context);
- List<UIComponent> toRemove = new ArrayList<UIComponent>();
- stateContext.setTrackViewModifications(false);
- for (UIComponent c : getChildren())
- if (!renderedSources.contains(((DynamicIncludeComponent)c).src))
- toRemove.add(c);
- this.getChildren().removeAll(toRemove);
- this.restoredSources = Collections.emptyList();
- this.wasPurged = true;
- stateContext.setTrackViewModifications(true);
- }
- private void buildView(FacesContext context, String src) {
- StateContext stateContext = StateContext.getStateContext(context);
- try {
- stateContext.setTrackViewModifications(false);
- DynamicIncludeComponent panel = new DynamicIncludeComponent();
- int index = findFreeIndex();
- panel.src = src;
- panel.index = index;
- panel.setId(getId() + index);
- this.getChildren().add(index, panel);
- setAttributesInFaceletContext();
- faceletContext.includeFacelet(panel, src);
- } catch (IOException e) {
- throw new RuntimeException(e);
- } finally {
- stateContext.setTrackViewModifications(true);
- }
- }
- private int findFreeIndex() {
- for (int i = 0; i <= this.getChildCount(); i++) {
- boolean free = true;
- for (UIComponent c : this.getChildren())
- if (i == ((DynamicIncludeComponent)c).index)
- free = false;
- if (free)
- return i;
- }
- throw new IllegalStateException("Impossible! Could not find available index.");
- }
- /**
- * FaceletContext is used during creation of components from a facelet
- * template. If these components have attributes with EL expressions
- * referring to what's in dynamicInclude attributes, we have to make
- * them available in FaceletContext.
- */
- private void setAttributesInFaceletContext() {
- for (Map.Entry<String, ValueExpression> var : valueExpressions.entrySet())
- faceletContext.getVariableMapper().setVariable(var.getKey(), var.getValue());
- }
- @Override
- public Object saveState(FacesContext context) {
- Object values[] = new Object[2];
- values[0] = super.saveState(context);
- values[1] = wasRendered ? renderedSources : restoredSources;
- return values;
- }
- /**
- * We rebuild subviews here. The children state will be restored
- * by StateManagementStrategy because it first restores state of a node
- * then processes its children.
- */
- @Override
- public void restoreState(FacesContext context, Object state) {
- Object values[] = (Object[]) state;
- super.restoreState(context, values[0]);
- this.restoredSources = (List<String>)values[1];
- for (String src : this.restoredSources)
- buildView(context, src);
- }
- /* getters and setters */
- public String getFamily() {
- return null;
- }
- public void setSrc(String src) {
- this.src = src;
- }
- public String getSrc() {
- if (src == null) {
- ValueExpression ve = getValueExpression(SRC_ATTRIBUTE);
- // Fast fix for poorly diagnosed error
- if (ve == null)
- ve = valueExpressions.get(SRC_ATTRIBUTE);
- this.src = (String) ve.getValue(getFacesContext().getELContext());
- }
- return this.src;
- }
- public void setFaceletContext(FaceletContext faceletContext) {
- this.faceletContext = faceletContext;
- }
- /**
- * This serves as root for possible subviews included by DynamicInclude.
- */
- public static class DynamicIncludeComponent extends UIComponentBase implements NamingContainer {
- // no need to preserve this, DynamicInclude restores this value
- private String src;
- private int index;
- @Override
- public String getFamily() {
- return null;
- }
- @Override
- public boolean isRendered() {
- return src.equals(((DynamicInclude)getParent()).getSrc());
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement