Coverage Report - org.apache.myfaces.view.facelets.tag.jsf.FaceletState
 
Classes in this File Line Coverage Branch Coverage Complexity
FaceletState
0%
0/60
0%
0/40
3.154
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *   http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.myfaces.view.facelets.tag.jsf;
 20  
 
 21  
 import java.io.Serializable;
 22  
 import java.util.HashMap;
 23  
 import java.util.Map;
 24  
 import javax.el.ValueExpression;
 25  
 
 26  
 import javax.faces.component.StateHolder;
 27  
 import javax.faces.component.UIComponentBase;
 28  
 import javax.faces.component.UIViewRoot;
 29  
 import javax.faces.context.FacesContext;
 30  
 
 31  
 public class FaceletState implements StateHolder, Serializable
 32  
 {
 33  
     /**
 34  
      * 
 35  
      */
 36  
     private static final long serialVersionUID = -7823771271935942737L;
 37  
     
 38  
     private Map<String, Object> stateMap;
 39  
     
 40  
     private Map<String, Map<String, ValueExpression>> bindingsMap;
 41  
     
 42  
     public FaceletState()
 43  0
     {
 44  0
     }
 45  
     
 46  
     public Object getState(String key)
 47  
     {
 48  0
         if(stateMap == null)
 49  
         {
 50  0
             return null;
 51  
         }
 52  0
         return stateMap.get(key);
 53  
     }
 54  
     
 55  
     public Object putState(String key, Object value)
 56  
     {
 57  0
         if (stateMap == null)
 58  
         {
 59  0
             stateMap = new HashMap<String, Object>();
 60  
         }
 61  0
         return stateMap.put(key, value);
 62  
     }
 63  
     
 64  
 
 65  
     public Object saveState(FacesContext context)
 66  
     {
 67  0
         UIViewRoot root = context.getViewRoot();
 68  0
         if (root != null && root.initialStateMarked())
 69  
         {
 70  0
             if (stateMap != null)
 71  
             {
 72  0
                 Object values[] = new Object[1];
 73  0
                 values[0] = UIComponentBase.saveAttachedState(context, stateMap);
 74  0
                 return values;
 75  
             }
 76  0
             return null;
 77  
         }
 78  
         else
 79  
         {
 80  0
             Object values[] = new Object[2];
 81  0
             values[0] = UIComponentBase.saveAttachedState(context, stateMap);
 82  
             // If the UIViewRoot instance was not marked with initial state, that means
 83  
             // we need to save the bindingsMap as well because it will not be restored
 84  
             // like with PSS, because in that case the view is built again using 
 85  
             // facelets algorithm.
 86  0
             values[1] = UIComponentBase.saveAttachedState(context, bindingsMap);
 87  0
             return values;
 88  
         }
 89  
     }
 90  
 
 91  
     @SuppressWarnings("unchecked")
 92  
     public void restoreState(FacesContext context, Object state)
 93  
     {
 94  0
         if (state == null)
 95  
         {
 96  0
             stateMap = null;
 97  0
             bindingsMap = null;
 98  0
             return;
 99  
         }
 100  0
         Object values[] = (Object[])state;
 101  0
         if (values.length == 2)
 102  
         {
 103  
             // Full state
 104  0
             stateMap = (Map<String,Object>) UIComponentBase.restoreAttachedState(context, values[0]);
 105  0
             bindingsMap = (Map<String,Map<String, ValueExpression>>) 
 106  
                 UIComponentBase.restoreAttachedState(context, values[1]);
 107  
         }
 108  
         else
 109  
         {
 110  0
             if (values[0] == null)
 111  
             {
 112  0
                 stateMap = null;
 113  
             }
 114  
             else
 115  
             {
 116  0
                 stateMap = (Map<String,Object>) UIComponentBase.restoreAttachedState(context, values[0]);
 117  
             }            
 118  
         }
 119  0
     }
 120  
 
 121  
     public boolean isTransient()
 122  
     {
 123  0
         return false;
 124  
     }
 125  
 
 126  
     public void setTransient(boolean newTransientValue)
 127  
     {
 128  0
     }
 129  
     
 130  
     public boolean isDynamic()
 131  
     {
 132  0
         return stateMap == null ? false : !stateMap.isEmpty();
 133  
     }
 134  
 
 135  
     public void putBinding(String uniqueId, String key, ValueExpression expr)
 136  
     {
 137  0
         if (bindingsMap == null)
 138  
         {
 139  0
             bindingsMap = new HashMap<String, Map<String, ValueExpression>>();
 140  
         }
 141  0
         Map<String, ValueExpression> bindings = bindingsMap.get(uniqueId);
 142  0
         if (bindings == null)
 143  
         {
 144  0
             bindings = new HashMap<String, ValueExpression>();
 145  0
             bindingsMap.put(uniqueId, bindings);
 146  
         }
 147  0
         bindings.put(key, expr);
 148  0
     }
 149  
     
 150  
     /**
 151  
      * A "Facelet Binding ValueExpression" is a ValueExpression used/generated by facelets algorithm
 152  
      * associated with an uniqueId, which usually is bound to the tagId. Components like c:forEach or
 153  
      * ui:param uses it and the reason behind this is avoid use VariableMapper to create EL Expressions
 154  
      * that later cannot be cached. Instead, the intention is make an indirection using 2 ValueExpression
 155  
      * instances. In that way, all EL Expressions can be cached, because VariableMapper will use an
 156  
      * instance that contains the uniqueId and the one stored in the map will have the real value or
 157  
      * EL Expression that points to the managed bean. (Remember each EL expression that uses a variable
 158  
      * stored in VariableMapper will copy the EL expression bound to the variable, so if the EL expression
 159  
      * value changes across views, all EL Expressions that contains a reference cannot be cached).
 160  
      * 
 161  
      * This map is something special, because its content is related to the view structure. It does not need
 162  
      * to be saved fully into the state, and it does not have any delta state, but it "evolves" with the initial
 163  
      * state.
 164  
      */
 165  
     public ValueExpression getBinding(String uniqueId, String key)
 166  
     {
 167  0
         if (bindingsMap == null)
 168  
         {
 169  0
             return null;
 170  
         }
 171  0
         Map<String, ValueExpression> bindings = bindingsMap.get(uniqueId);
 172  0
         if (bindings == null)
 173  
         {
 174  0
             return null;
 175  
         }
 176  0
         return bindings.get(key);
 177  
     }
 178  
     
 179  
     public Map<String, Map<String, ValueExpression>> getBindings()
 180  
     {
 181  0
         return bindingsMap;
 182  
     }
 183  
 
 184  
     @Override
 185  
     public int hashCode()
 186  
     {
 187  0
         int hash = 7;
 188  0
         hash = 79 * hash + (this.stateMap != null ? this.stateMap.hashCode() : 0);
 189  0
         return hash;
 190  
     }
 191  
 
 192  
     @Override
 193  
     public boolean equals(Object obj)
 194  
     {
 195  0
         if (obj == null)
 196  
         {
 197  0
             return false;
 198  
         }
 199  0
         if (getClass() != obj.getClass())
 200  
         {
 201  0
             return false;
 202  
         }
 203  0
         final FaceletState other = (FaceletState) obj;
 204  0
         if (this.stateMap != other.stateMap && (this.stateMap == null || !this.stateMap.equals(other.stateMap)))
 205  
         {
 206  0
             return false;
 207  
         }
 208  0
         return true;
 209  
     }
 210  
 
 211  
 }