Advertisement
Guest User

Untitled

a guest
Apr 3rd, 2015
419
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.22 KB | None | 0 0
  1. package pl.horus.wf.web.commons.component;
  2.  
  3. import com.sun.faces.context.StateContext;
  4.  
  5. import javax.el.ValueExpression;
  6. import javax.faces.component.*;
  7. import javax.faces.context.FacesContext;
  8. import javax.faces.view.facelets.FaceletContext;
  9. import java.io.IOException;
  10. import java.util.*;
  11.  
  12. /**
  13.  * This component allows including facelets dynamically. It is using
  14.  * preserved FaceletContext to build component trees based on the view path.
  15.  * This FaceletContext is enriched with attributes passed to the
  16.  * dynamicInclude tag.
  17.  *
  18.  * Initially subtrees are built in the rendering phase. Then on postback
  19.  * request they are rebuilt in restoreView phase.
  20.  */
  21. public class DynamicInclude extends UIComponentBase {
  22.  
  23.   private static final String SRC_ATTRIBUTE = "src";
  24.  
  25.   private Map<String, ValueExpression> valueExpressions = Collections.emptyMap();
  26.   private List<String> renderedSources = new ArrayList<String>();
  27.   private List<String> restoredSources = Collections.emptyList();
  28.   // for ajax requests this will stay false
  29.   private boolean wasRendered = false;
  30.   private boolean wasPurged = false;
  31.   private FaceletContext faceletContext;
  32.   private String src;
  33.  
  34.   public DynamicInclude() {}
  35.  
  36.   public void addValueExpression(String key, ValueExpression valueExpression) {
  37.     if (valueExpressions == Collections.EMPTY_MAP)
  38.       valueExpressions = new HashMap<String, ValueExpression>();
  39.     valueExpressions.put(key, valueExpression);
  40.   }
  41.  
  42.   @Override
  43.   public void encodeBegin(FacesContext context) throws IOException {
  44.     wasRendered = true;
  45.     this.src = calculateSrc();
  46.     if (isRendered()) {
  47.       String src = getSrc();
  48.  
  49.       if (!renderedSources.contains(src))
  50.         // As soon as we detect the first inconsistency between restored and
  51.         // rendered views, we purge restored views. Otherwise we reuse restored
  52.         // view and mark it as rendered.
  53.         if (restoredSources.indexOf(src) == renderedSources.size())
  54.           renderedSources.add(src);
  55.         else if (!wasPurged)
  56.           purgeRestoredChildren(context);
  57.  
  58.       if (!renderedSources.contains(src)) {
  59.         buildView(context, src);
  60.         renderedSources.add(src);
  61.       }
  62.     }
  63.   }
  64.  
  65.   /**
  66.    * Remove all restored views except those marked as rendered.
  67.    */
  68.   private void purgeRestoredChildren(FacesContext context) {
  69.     StateContext stateContext = StateContext.getStateContext(context);
  70.     List<UIComponent> toRemove = new ArrayList<UIComponent>();
  71.     stateContext.setTrackViewModifications(false);
  72.     for (UIComponent c : getChildren())
  73.       if (!renderedSources.contains(((DynamicIncludeComponent)c).src))
  74.         toRemove.add(c);
  75.  
  76.     this.getChildren().removeAll(toRemove);
  77.     this.restoredSources = Collections.emptyList();
  78.     this.wasPurged = true;
  79.     stateContext.setTrackViewModifications(true);
  80.   }
  81.  
  82.   private void buildView(FacesContext context, String src) {
  83.     StateContext stateContext = StateContext.getStateContext(context);
  84.     try {
  85.       stateContext.setTrackViewModifications(false);
  86.       DynamicIncludeComponent panel = new DynamicIncludeComponent();
  87.       int index = findFreeIndex();
  88.       panel.src = src;
  89.       panel.index = index;
  90.       panel.setId(getId() + index);
  91.       this.getChildren().add(index, panel);
  92.       setAttributesInFaceletContext();
  93.       faceletContext.includeFacelet(panel, src);
  94.     } catch (IOException e) {
  95.       throw new RuntimeException(e);
  96.     } finally {
  97.       stateContext.setTrackViewModifications(true);
  98.     }
  99.   }
  100.  
  101.   private int findFreeIndex() {
  102.     for (int i = 0; i <= this.getChildCount(); i++) {
  103.       boolean free = true;
  104.       for (UIComponent c : this.getChildren())
  105.         if (i == ((DynamicIncludeComponent)c).index)
  106.           free = false;
  107.       if (free)
  108.         return i;
  109.     }
  110.     throw new IllegalStateException("Impossible! Could not find available index.");
  111.   }
  112.  
  113.   /**
  114.    * FaceletContext is used during creation of components from a facelet
  115.    * template. If these components have attributes with EL expressions
  116.    * referring to what's in dynamicInclude attributes, we have to make
  117.    * them available in FaceletContext.
  118.    */
  119.   private void setAttributesInFaceletContext() {
  120.     for (Map.Entry<String, ValueExpression> var : valueExpressions.entrySet())
  121.       faceletContext.getVariableMapper().setVariable(var.getKey(), var.getValue());
  122.   }
  123.  
  124.   @Override
  125.   public Object saveState(FacesContext context) {
  126.     Object values[] = new Object[2];
  127.     values[0] = super.saveState(context);
  128.     values[1] = wasRendered ? renderedSources : restoredSources;
  129.     return values;
  130.   }
  131.  
  132.   /**
  133.    * We rebuild subviews here. The children state will be restored
  134.    * by StateManagementStrategy because it first restores state of a node
  135.    * then processes its children.
  136.    */
  137.   @Override
  138.   public void restoreState(FacesContext context, Object state) {
  139.     Object values[] = (Object[]) state;
  140.     super.restoreState(context, values[0]);
  141.     this.restoredSources = (List<String>)values[1];
  142.  
  143.     for (String src : this.restoredSources)
  144.       buildView(context, src);
  145.   }
  146.  
  147.   /* getters and setters */
  148.   public String getFamily() {
  149.     return null;
  150.   }
  151.  
  152.   public void setSrc(String src) {
  153.     this.src = src;
  154.   }
  155.  
  156.   public String getSrc() {
  157.     if (src == null)
  158.       this.src = calculateSrc();
  159.     return this.src;
  160.   }
  161.  
  162.   private String calculateSrc() {
  163.     ValueExpression ve = getValueExpression(SRC_ATTRIBUTE);
  164.     // Fast fix for poorly diagnosed error
  165.     if (ve == null)
  166.       ve = valueExpressions.get(SRC_ATTRIBUTE);
  167.     return (String) ve.getValue(getFacesContext().getELContext());
  168.   }
  169.  
  170.   public void setFaceletContext(FaceletContext faceletContext) {
  171.     this.faceletContext = faceletContext;
  172.   }
  173.  
  174.   /**
  175.    * This serves as root for possible subviews included by DynamicInclude.
  176.    */
  177.   public static class DynamicIncludeComponent extends UIComponentBase implements NamingContainer {
  178.     // no need to preserve this, DynamicInclude restores this value
  179.     private String src;
  180.     private int index;
  181.  
  182.     @Override
  183.     public String getFamily() {
  184.       return null;
  185.     }
  186.  
  187.     @Override
  188.     public boolean isRendered() {
  189.       return src.equals(((DynamicInclude)getParent()).getSrc());
  190.     }
  191.   }
  192. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement