Coverage Report - javax.faces.component._DeltaStateHelper
 
Classes in this File Line Coverage Branch Coverage Complexity
_DeltaStateHelper
80%
213/265
71%
133/186
3.417
_DeltaStateHelper$InternalDeltaListMap
50%
4/8
N/A
3.417
_DeltaStateHelper$InternalList
78%
15/19
70%
7/10
3.417
_DeltaStateHelper$InternalMap
80%
20/25
80%
8/10
3.417
 
 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 javax.faces.component;
 20  
 
 21  
 import java.io.Serializable;
 22  
 import java.util.ArrayList;
 23  
 import java.util.Collection;
 24  
 import java.util.HashMap;
 25  
 import java.util.Iterator;
 26  
 import java.util.List;
 27  
 import java.util.Map;
 28  
 
 29  
 import javax.el.ValueExpression;
 30  
 import javax.faces.context.FacesContext;
 31  
 
 32  
 /**
 33  
  * A delta enabled state holder implementing the StateHolder Interface. 
 34  
  * <p>
 35  
  * Components implementing the PartalStateHolder interface have an initial state
 36  
  * and delta states, the initial state is the one holding all root values
 37  
  * and deltas store differences to the initial states
 38  
  * </p>
 39  
  * <p>
 40  
  * For components not implementing partial state saving only the initial states are
 41  
  * of importance, everything is stored and restored continously there
 42  
  * </p> 
 43  
  * <p>
 44  
  * The state helper seems to have three internal storage mechanisms:
 45  
  * one being a list which stores plain values,
 46  
  * one being a key value pair which stores key values in maps
 47  
  * add serves the plain list type while put serves the 
 48  
  * key value type, 
 49  
  * the third is the value which has to be stored plainly as is!
 50  
  * </p>
 51  
  * In other words, this map can be seen as a composite map. It has two maps: 
 52  
  * initial state map and delta map.
 53  
  * <p> 
 54  
  * If delta map is used (method component.initialStateMarked() ), 
 55  
  * base or initial state map cannot be changed, since all changes 
 56  
  * should be tracked on delta map.
 57  
  * </p>
 58  
  * <p> 
 59  
  * The intention of this class is just hold property values
 60  
  * and do a clean separation between initial state and delta.
 61  
  * </p>
 62  
  * <p>
 63  
  * The code from this class comes from a refactor of 
 64  
  * org.apache.myfaces.trinidad.bean.util.PropertyHashMap
 65  
  * </p>
 66  
  * <p>
 67  
  * The context from this class comes and that should be taken into account
 68  
  * is this:
 69  
  * </p>
 70  
  * <p> 
 71  
  * First request:
 72  
  * </p>
 73  
  * <ul>
 74  
  *   <li> A new template is created (using 
 75  
  *   javax.faces.view.ViewDeclarationLanguage.buildView method)
 76  
  *   and component.markInitialState is called from its related TagHandler classes 
 77  
  *  (see javax.faces.view.facelets.ComponentHandler ).
 78  
  *   When this method is executed, the component tree was populated from the values
 79  
  *   set in the facelet abstract syntax tree (or in other words composition of 
 80  
  *   facelets templates). </li>
 81  
  *   <li> From this point all updates on the variables are considered "delta". </li>
 82  
  *   <li> SaveState, if initialStateMarked is true, only delta is saved. </li>
 83  
  * </ul>
 84  
  * <p>
 85  
  * Second request (and next ones)
 86  
  * </p>
 87  
  * <ul>
 88  
  *   <li> A new template is created and component.markInitialState is called from
 89  
  *   its related TagHandler classes again. In this way, components like c:forEach 
 90  
  *   or c:if, that add or remove components could notify about this and handle 
 91  
  *   them properly (see javax.faces.view.StateManagementStrategy). Note that a 
 92  
  *   component restored using this method is no different as the same component 
 93  
  *   at the first request at the same time. </li>
 94  
  *   <li> A call for restoreState is done, passing the delta as object value. If no 
 95  
  *   delta, the state is complete and no call is triggered. </li>
 96  
  *   <li> Lifecycle occur, changing the necessary stuff. </li>
 97  
  *   <li> SaveState, if initialStateMarked is true, only delta is saved. </li>
 98  
  * </ul>
 99  
  * <p>
 100  
  * From the previous analysis, the following conclusions arise:
 101  
  * <ul>
 102  
  *   <li>This class only needs to keep track of delta changes, so when 
 103  
  *   restoreState/saveState is called, the right objects are passed.</li>
 104  
  *   <li>UIComponent.clearInitialState is used to reset the partial
 105  
  *   state holder to a non delta state, so the state to be saved by
 106  
  *   saveState is no longer a delta instead is a full state. If a call
 107  
  *   to clearInitialState occur it is not expected a call for 
 108  
  *   UIComponent.markInitialState occur on the current request.</li>
 109  
  *   <li>The state is handled in the same way on UIData, so components
 110  
  *   inside UIData share its state on all rows. There is no way to save 
 111  
  *   delta per row.</li>
 112  
  *   <li>The map backed by method put(Serializable,String,Object) is
 113  
  *   a replacement of UIComponentBase.attributesMap and UIComponent.bindings map.
 114  
  *   Note that on jsf 1.2, instances saved on attributesMap should not be
 115  
  *   StateHolder, but on jsf 2.0 it is possible to have it. PartialStateHolder
 116  
  *   instances are not handled in this map, or in other words delta state is not
 117  
  *   handled in this classes (markInitialState and clearInitialState is not propagated).</li>
 118  
  *   <li>The list backed by method add(Serializable,Object) should be (is not) a 
 119  
  *   replacement of UIComponentBase.facesListeners, but note that StateHelper
 120  
  *   does not implement PartialStateHolder, and facesListener could have instances
 121  
  *   of that class that needs to be notified when UIComponent.markInitialState or
 122  
  *   UIComponent.clearInitialState is called, or in other words facesListeners
 123  
  *   should deal with PartialStateHolder instances.</li>
 124  
  *   <li>The list backed by method add(Serializable,Object) is 
 125  
  *   a replacement of UIViewRoot.phaseListeners list. Note that instances of
 126  
  *   PhaseListener are not expected to implement StateHolder or PartialStateHolder.</li>
 127  
  * </ul>
 128  
  * </p>
 129  
  * <p>
 130  
  * NOTE: The current implementation of StateHelper on RI does not handle
 131  
  * stateHolder values internally. To prevent problems when developers create
 132  
  * custom components we should do this too. But anyway, the code that 
 133  
  * handle this case should be let here as comment, if some day this feature
 134  
  * is provided. Note than stateHolder aware properties like converter,
 135  
  * validator or listeners should deal with StateHolder or PartialStateHolder
 136  
  * on component classes. 
 137  
  * 
 138  
  * </p>
 139  
  */
 140  
 class _DeltaStateHelper implements StateHelper, TransientStateHelper, TransientStateHolder
 141  
 {
 142  
 
 143  
     /**
 144  
      * We need to hold a component instance because:
 145  
      * 
 146  
      * - The component is the one who knows if we are on initial or delta mode
 147  
      * - eval assume calls to component.ValueExpression
 148  
      */
 149  
     private UIComponent _component;
 150  
 
 151  
     /**
 152  
      * This map holds the full current state
 153  
      */
 154  
     private Map<Serializable, Object> _fullState;
 155  
 
 156  
     /**
 157  
      * This map only keep track of delta changes to be saved
 158  
      */
 159  
     private Map<Serializable, Object> _deltas;
 160  
     
 161  
     private Map<Object, Object> _transientState;
 162  
     
 163  
     //private Map<Serializable, Object> _initialState;
 164  
     private Object[] _initialState;
 165  
     
 166  
     /**
 167  
      * This map keep track of StateHolder keys, to be saved when
 168  
      * saveState is called. 
 169  
      */
 170  
     //private Set<Serializable> _stateHolderKeys;  
 171  
 
 172  1204
     private boolean _transient = false;
 173  
 
 174  
     /**
 175  
      * This is a copy-on-write map of the full state after markInitialState()
 176  
      * was called, but before any delta is written that is not part of
 177  
      * the initial state (value, localValueSet, submittedValue, valid).
 178  
      * The intention is allow to reset the StateHelper when copyFullInitialState
 179  
      * is set to true.
 180  
      */
 181  
     private Map<Serializable, Object> _initialFullState;
 182  
     
 183  
     /**
 184  
      * Indicates if a copy-on-write map is created to allow reset the state
 185  
      * of this StateHelper.
 186  
      */
 187  
     private boolean _copyFullInitialState;
 188  
 
 189  
     public _DeltaStateHelper(UIComponent component)
 190  
     {
 191  1204
         super();
 192  1204
         this._component = component;
 193  1204
         _fullState = new HashMap<Serializable, Object>();
 194  1204
         _deltas = null;
 195  1204
         _transientState = null;
 196  1204
         _initialFullState = null;
 197  1204
         _copyFullInitialState = false;
 198  
         //_stateHolderKeys = new HashSet<Serializable>();
 199  1204
     }
 200  
 
 201  
     /**
 202  
      * Used to create delta map on demand
 203  
      * 
 204  
      * @return
 205  
      */
 206  
     private boolean _createDeltas(Serializable key)
 207  
     {
 208  22488
         if (isInitialStateMarked())
 209  
         {
 210  332
             if (_copyFullInitialState && _initialFullState == null)
 211  
             {
 212  182
                 if (_initialState == null)
 213  
                 {
 214  
                     // Copy it directly
 215  86
                     _initialFullState = new HashMap<Serializable, Object>();
 216  86
                     copyMap(_component.getFacesContext(), _fullState, _initialFullState);
 217  
                 }
 218  
                 else
 219  
                 {
 220  
                     // Create only if the passed key is not part of the defined initial state
 221  96
                     boolean keyInInitialState = false;
 222  216
                     for (int i = 0; i < _initialState.length; i+=2)
 223  
                     {
 224  216
                         Serializable key2 = (Serializable) _initialState[i];
 225  216
                         if (key.equals(key2))
 226  
                         {
 227  96
                             keyInInitialState = true;
 228  96
                             break;
 229  
                         }
 230  
                     }
 231  96
                     if (!keyInInitialState)
 232  
                     {
 233  
                         // Copy it directly, but note in this case if the initialFullState map
 234  
                         // contains some key already defined in initialState, this key must be
 235  
                         // overriden. It is better to do in that way, because it is possible
 236  
                         // to skip resetState() if the view cannot be recycled.
 237  0
                         _initialFullState = new HashMap<Serializable, Object>();
 238  0
                         copyMap(_component.getFacesContext(), _fullState, _initialFullState);
 239  
                         /*
 240  
                         for (int i = 0; i < _initialState.length; i+=2)
 241  
                         {
 242  
                             Serializable key2 = (Serializable) _initialState[i];
 243  
                             Object defaultValue = _initialState[i+1];
 244  
                             _initialFullState.put(key2, defaultValue);
 245  
                         }*/
 246  
                     }
 247  
                 }
 248  
             }
 249  332
             if (_deltas == null)
 250  
             {
 251  110
                 _deltas = new HashMap<Serializable, Object>(2);
 252  
             }
 253  332
             return true;
 254  
         }
 255  
 
 256  22156
         return false;
 257  
     }
 258  
     
 259  
     void setCopyFullInitialState(boolean value)
 260  
     {
 261  328
         _copyFullInitialState = value;
 262  328
     }
 263  
     
 264  
     private static void copyMap(FacesContext context, 
 265  
             Map<Serializable, Object> sourceMap, 
 266  
             Map<Serializable, Object> targetMap)
 267  
     {
 268  86
         Map serializableMap = sourceMap;
 269  
         Map.Entry<Serializable, Object> entry;
 270  
 
 271  86
         Iterator<Map.Entry<Serializable, Object>> it = serializableMap
 272  
                 .entrySet().iterator();
 273  132
         while (it.hasNext())
 274  
         {
 275  46
             entry = it.next();
 276  46
             Serializable key = entry.getKey();
 277  46
             Object value = entry.getValue();
 278  
 
 279  
             // The condition in which the call to saveAttachedState
 280  
             // is to handle List, StateHolder or non Serializable instances.
 281  
             // we check it here, to prevent unnecessary calls.
 282  46
             if (value instanceof StateHolder ||
 283  
                 value instanceof List ||
 284  
                 !(value instanceof Serializable))
 285  
             {
 286  36
                 Object savedValue = UIComponentBase.saveAttachedState(context,
 287  
                     value);
 288  
 
 289  36
                 targetMap.put(key, UIComponentBase.restoreAttachedState(context,
 290  
                         savedValue));
 291  36
             }
 292  10
             else if (!(value instanceof Serializable))
 293  
             {
 294  
                 Object newInstance;
 295  
                 try
 296  
                 {
 297  0
                     newInstance = entry.getValue().getClass().newInstance();
 298  
                 }
 299  0
                 catch (InstantiationException e)
 300  
                 {
 301  0
                     throw new RuntimeException("Could not restore StateHolder of type " + 
 302  
                             entry.getValue().getClass().getName()
 303  
                             + " (missing no-args constructor?)", e);
 304  
                 }
 305  0
                 catch (IllegalAccessException e)
 306  
                 {
 307  0
                     throw new RuntimeException(e);
 308  0
                 }
 309  0
                 targetMap.put(key, newInstance);
 310  0
             }
 311  
             else
 312  
             {
 313  10
                 targetMap.put(key, value);
 314  
             }
 315  46
         }
 316  86
     }
 317  
     
 318  
     protected boolean isInitialStateMarked()
 319  
     {
 320  22808
         return _component.initialStateMarked();
 321  
     }
 322  
 
 323  
     public void add(Serializable key, Object value)
 324  
     {
 325  70
         if (_createDeltas(key))
 326  
         {
 327  
             //Track delta case
 328  46
             Map<Object, Boolean> deltaListMapValues = (Map<Object, Boolean>) _deltas
 329  
                     .get(key);
 330  46
             if (deltaListMapValues == null)
 331  
             {
 332  36
                 deltaListMapValues = new InternalDeltaListMap<Object, Boolean>(
 333  
                         3);
 334  36
                 _deltas.put(key, deltaListMapValues);
 335  
             }
 336  46
             deltaListMapValues.put(value, Boolean.TRUE);
 337  
         }
 338  
 
 339  
         //Handle change on full map
 340  70
         List<Object> fullListValues = (List<Object>) _fullState.get(key);
 341  70
         if (fullListValues == null)
 342  
         {
 343  44
             fullListValues = new InternalList<Object>(3);
 344  44
             _fullState.put(key, fullListValues);
 345  
         }
 346  70
         fullListValues.add(value);
 347  70
     }
 348  
 
 349  
     public Object eval(Serializable key)
 350  
     {
 351  798
         Object returnValue = _fullState.get(key);
 352  798
         if (returnValue != null)
 353  
         {
 354  390
             return returnValue;
 355  
         }
 356  408
         ValueExpression expression = _component.getValueExpression(key
 357  
                 .toString());
 358  408
         if (expression != null)
 359  
         {
 360  60
             return expression.getValue(_component.getFacesContext()
 361  
                     .getELContext());
 362  
         }
 363  348
         return null;
 364  
     }
 365  
 
 366  
     public Object eval(Serializable key, Object defaultValue)
 367  
     {
 368  486
         Object returnValue = _fullState.get(key);
 369  486
         if (returnValue != null)
 370  
         {
 371  46
             return returnValue;
 372  
         }
 373  440
         ValueExpression expression = _component.getValueExpression(key
 374  
                 .toString());
 375  440
         if (expression != null)
 376  
         {
 377  40
             return expression.getValue(_component.getFacesContext()
 378  
                     .getELContext());
 379  
         }
 380  400
         return defaultValue;
 381  
     }
 382  
 
 383  
     public Object get(Serializable key)
 384  
     {
 385  24192
         return _fullState.get(key);
 386  
     }
 387  
 
 388  
     public Object put(Serializable key, Object value)
 389  
     {
 390  22142
         Object returnValue = null;
 391  22142
         if (_createDeltas(key))
 392  
         {
 393  158
             if (_deltas.containsKey(key))
 394  
             {
 395  62
                 returnValue = _deltas.put(key, value);
 396  62
                 _fullState.put(key, value);
 397  
             }
 398  96
             else if (value == null && !_fullState.containsKey(key))
 399  
             {
 400  24
                 returnValue = null;
 401  
             }
 402  
             else
 403  
             {
 404  72
                 _deltas.put(key, value);
 405  72
                 returnValue = _fullState.put(key, value);
 406  
             }
 407  
         }
 408  
         else
 409  
         {
 410  
             /*
 411  
             if (value instanceof StateHolder)
 412  
             {
 413  
                 _stateHolderKeys.add(key);
 414  
             }
 415  
             */
 416  21984
             returnValue = _fullState.put(key, value);
 417  
         }
 418  22142
         return returnValue;
 419  
     }
 420  
 
 421  
     public Object put(Serializable key, String mapKey, Object value)
 422  
     {
 423  236
         boolean returnSet = false;
 424  236
         Object returnValue = null;
 425  236
         if (_createDeltas(key))
 426  
         {
 427  
             //Track delta case
 428  92
             Map<String, Object> mapValues = (Map<String, Object>) _deltas
 429  
                     .get(key);
 430  92
             if (mapValues == null)
 431  
             {
 432  62
                 mapValues = new InternalMap<String, Object>();
 433  62
                 _deltas.put(key, mapValues);
 434  
             }
 435  92
             if (mapValues.containsKey(mapKey))
 436  
             {
 437  4
                 returnValue = mapValues.put(mapKey, value);
 438  4
                 returnSet = true;
 439  
             }
 440  
             else
 441  
             {
 442  88
                 mapValues.put(mapKey, value);
 443  
             }
 444  
         }
 445  
 
 446  
         //Handle change on full map
 447  236
         Map<String, Object> mapValues = (Map<String, Object>) _fullState
 448  
                 .get(key);
 449  236
         if (mapValues == null)
 450  
         {
 451  176
             mapValues = new InternalMap<String, Object>();
 452  176
             _fullState.put(key, mapValues);
 453  
         }
 454  236
         if (returnSet)
 455  
         {
 456  4
             mapValues.put(mapKey, value);
 457  
         }
 458  
         else
 459  
         {
 460  232
             returnValue = mapValues.put(mapKey, value);
 461  
         }
 462  236
         return returnValue;
 463  
     }
 464  
 
 465  
     public Object remove(Serializable key)
 466  
     {
 467  6
         Object returnValue = null;
 468  6
         if (_createDeltas(key))
 469  
         {
 470  4
             if (_deltas.containsKey(key))
 471  
             {
 472  
                 // Keep track of the removed values using key/null pair on the delta map
 473  2
                 returnValue = _deltas.put(key, null);
 474  2
                 _fullState.remove(key);
 475  
             }
 476  
             else
 477  
             {
 478  
                 // Keep track of the removed values using key/null pair on the delta map
 479  2
                 _deltas.put(key, null);
 480  2
                 returnValue = _fullState.remove(key);
 481  
             }
 482  
         }
 483  
         else
 484  
         {
 485  2
             returnValue = _fullState.remove(key);
 486  
         }
 487  6
         return returnValue;
 488  
     }
 489  
 
 490  
     public Object remove(Serializable key, Object valueOrKey)
 491  
     {
 492  
         // Comment by lu4242 : The spec javadoc says if it is a Collection 
 493  
         // or Map deal with it. But the intention of this method is work 
 494  
         // with add(?,?) and put(?,?,?), this ones return instances of 
 495  
         // InternalMap and InternalList to prevent mixing, so to be 
 496  
         // consistent we'll cast to those classes here.
 497  
         
 498  40
         Object collectionOrMap = _fullState.get(key);
 499  40
         Object returnValue = null;
 500  40
         if (collectionOrMap instanceof InternalMap)
 501  
         {
 502  14
             if (_createDeltas(key))
 503  
             {
 504  12
                 returnValue = _removeValueOrKeyFromMap(_deltas, key,
 505  
                         valueOrKey, true);
 506  12
                 _removeValueOrKeyFromMap(_fullState, key, valueOrKey, false);
 507  
             }
 508  
             else
 509  
             {
 510  2
                 returnValue = _removeValueOrKeyFromMap(_fullState, key,
 511  
                         valueOrKey, false);
 512  
             }
 513  
         }
 514  26
         else if (collectionOrMap instanceof InternalList)
 515  
         {
 516  20
             if (_createDeltas(key))
 517  
             {
 518  20
                 returnValue = _removeValueOrKeyFromCollectionDelta(_deltas,
 519  
                         key, valueOrKey);
 520  20
                 _removeValueOrKeyFromCollection(_fullState, key, valueOrKey);
 521  
             }
 522  
             else
 523  
             {
 524  0
                 returnValue = _removeValueOrKeyFromCollection(_fullState, key,
 525  
                         valueOrKey);
 526  
             }
 527  
         }
 528  40
         return returnValue;
 529  
     }
 530  
 
 531  
     private static Object _removeValueOrKeyFromCollectionDelta(
 532  
             Map<Serializable, Object> stateMap, Serializable key,
 533  
             Object valueOrKey)
 534  
     {
 535  20
         Object returnValue = null;
 536  20
         Map<Object, Boolean> c = (Map<Object, Boolean>) stateMap.get(key);
 537  20
         if (c != null)
 538  
         {
 539  14
             if (c.containsKey(valueOrKey))
 540  
             {
 541  8
                 returnValue = valueOrKey;
 542  
             }
 543  14
             c.put(valueOrKey, Boolean.FALSE);
 544  
         }
 545  20
         return returnValue;
 546  
     }
 547  
 
 548  
     private static Object _removeValueOrKeyFromCollection(
 549  
             Map<Serializable, Object> stateMap, Serializable key,
 550  
             Object valueOrKey)
 551  
     {
 552  20
         Object returnValue = null;
 553  20
         Collection c = (Collection) stateMap.get(key);
 554  20
         if (c != null)
 555  
         {
 556  20
             if (c.remove(valueOrKey))
 557  
             {
 558  20
                 returnValue = valueOrKey;
 559  
             }
 560  20
             if (c.isEmpty())
 561  
             {
 562  12
                 stateMap.remove(key);
 563  
             }
 564  
         }
 565  20
         return returnValue;
 566  
     }
 567  
 
 568  
     private static Object _removeValueOrKeyFromMap(
 569  
             Map<Serializable, Object> stateMap, Serializable key,
 570  
             Object valueOrKey, boolean delta)
 571  
     {
 572  26
         if (valueOrKey == null)
 573  
         {
 574  0
             return null;
 575  
         }
 576  
 
 577  26
         Object returnValue = null;
 578  26
         Map<String, Object> map = (Map<String, Object>) stateMap.get(key);
 579  26
         if (map != null)
 580  
         {
 581  26
             if (delta)
 582  
             {
 583  
                 // Keep track of the removed values using key/null pair on the delta map
 584  12
                 returnValue = map.put((String) valueOrKey, null);
 585  
             }
 586  
             else
 587  
             {
 588  14
                 returnValue = map.remove(valueOrKey);
 589  
             }
 590  
 
 591  26
             if (map.isEmpty())
 592  
             {
 593  
                 //stateMap.remove(key);
 594  6
                 stateMap.put(key, null);
 595  
             }
 596  
         }
 597  26
         return returnValue;
 598  
     }
 599  
 
 600  
     public boolean isTransient()
 601  
     {
 602  2
         return _transient;
 603  
     }
 604  
 
 605  
     /**
 606  
      * Serializing cod
 607  
      * the serialized data structure consists of key value pairs unless the value itself is an internal array
 608  
      * or a map in case of an internal array or map the value itself is another array with its initial value
 609  
      * myfaces.InternalArray, myfaces.internalMap
 610  
      *
 611  
      * the internal Array is then mapped to another array
 612  
      *
 613  
      * the internal Map again is then mapped to a map with key value pairs
 614  
      *
 615  
      *
 616  
      */
 617  
     public Object saveState(FacesContext context)
 618  
     {
 619  222
         Map serializableMap = (isInitialStateMarked()) ? _deltas : _fullState;
 620  
 
 621  222
         if (_initialState != null && _deltas != null && !_deltas.isEmpty()
 622  
             && isInitialStateMarked())
 623  
         {
 624  
             // Before save the state, check if the property was changed from the
 625  
             // initial state value. If the property was changed but it has the
 626  
             // same value from the one in the initial state, we can remove it
 627  
             // from delta, because when the view is built again, it will be
 628  
             // restored to the same state. This check suppose some additional
 629  
             // map.get() calls when saving the state, but using it only in properties
 630  
             // that are expected to change over lifecycle (value, localValueSet,
 631  
             // submittedValue, valid), is worth to do it, because those ones
 632  
             // always generated delta changes.
 633  70
             for (int i = 0; i < _initialState.length; i+=2)
 634  
             {
 635  56
                 Serializable key = (Serializable) _initialState[i];
 636  56
                 Object defaultValue = _initialState[i+1];
 637  
                 
 638  
                 // Check only if there is delta state for that property, in other
 639  
                 // case it is not necessary. Remember it is possible to have
 640  
                 // null values inside the Map.
 641  56
                 if (_deltas.containsKey(key))
 642  
                 {
 643  14
                     Object deltaValue = _deltas.get(key);
 644  14
                     if (deltaValue == null && defaultValue == null)
 645  
                     {
 646  0
                         _deltas.remove(key);
 647  0
                         if (_deltas.isEmpty())
 648  
                         {
 649  0
                             break;
 650  
                         }
 651  
                     }
 652  14
                     if (deltaValue != null && deltaValue.equals(defaultValue))
 653  
                     {
 654  0
                         _deltas.remove(key);
 655  0
                         if (_deltas.isEmpty())
 656  
                         {
 657  0
                             break;
 658  
                         }
 659  
                     }
 660  
                 }
 661  
             }
 662  
         }
 663  222
         if (serializableMap == null || serializableMap.size() == 0)
 664  
         {
 665  130
             return null;
 666  
         }
 667  
         
 668  
         /*
 669  
         int stateHolderKeyCount = 0;
 670  
         if (isInitalStateMarked())
 671  
         {
 672  
             for (Iterator<Serializable> it = _stateHolderKeys.iterator(); it.hasNext();)
 673  
             {
 674  
                 Serializable key = it.next();
 675  
                 if (!_deltas.containsKey(key))
 676  
                 {
 677  
                     stateHolderKeyCount++;
 678  
                 }
 679  
             }
 680  
         }*/
 681  
         
 682  
         Map.Entry<Serializable, Object> entry;
 683  
         //entry == key, value, key, value
 684  92
         Object[] retArr = new Object[serializableMap.entrySet().size() * 2];
 685  
         //Object[] retArr = new Object[serializableMap.entrySet().size() * 2 + stateHolderKeyCount]; 
 686  
 
 687  92
         Iterator<Map.Entry<Serializable, Object>> it = serializableMap
 688  
                 .entrySet().iterator();
 689  92
         int cnt = 0;
 690  206
         while (it.hasNext())
 691  
         {
 692  114
             entry = it.next();
 693  114
             retArr[cnt] = entry.getKey();
 694  
 
 695  114
             Object value = entry.getValue();
 696  
             
 697  
             // The condition in which the call to saveAttachedState
 698  
             // is to handle List, StateHolder or non Serializable instances.
 699  
             // we check it here, to prevent unnecessary calls.
 700  114
             if (value instanceof StateHolder ||
 701  
                 value instanceof List ||
 702  
                 !(value instanceof Serializable))
 703  
             {
 704  72
                 Object savedValue = UIComponentBase.saveAttachedState(context,
 705  
                     value);
 706  72
                 retArr[cnt + 1] = savedValue;
 707  72
             }
 708  
             else
 709  
             {
 710  42
                 retArr[cnt + 1] = value;
 711  
             }
 712  114
             cnt += 2;
 713  114
         }
 714  
         
 715  
         /*
 716  
         if (isInitalStateMarked())
 717  
         {
 718  
             for (Iterator<Serializable> it2 = _stateHolderKeys.iterator(); it.hasNext();)
 719  
             {
 720  
                 Serializable key = it2.next();
 721  
                 if (!_deltas.containsKey(key))
 722  
                 {
 723  
                     retArr[cnt] = key;
 724  
                     Object value = _fullState.get(key);
 725  
                     if (value instanceof PartialStateHolder)
 726  
                     {
 727  
                         //Could contain delta, save it as _AttachedDeltaState
 728  
                         PartialStateHolder holder = (PartialStateHolder) value;
 729  
                         if (holder.isTransient())
 730  
                         {
 731  
                             retArr[cnt + 1] = null;
 732  
                         }
 733  
                         else
 734  
                         {
 735  
                             retArr[cnt + 1] = new _AttachedDeltaWrapper(value.getClass(), holder.saveState(context));
 736  
                         }
 737  
                     }
 738  
                     else
 739  
                     {
 740  
                         //Save everything
 741  
                         retArr[cnt + 1] = UIComponentBase.saveAttachedState(context, _fullState.get(key));
 742  
                     }
 743  
                     cnt += 2;
 744  
                 }
 745  
             }
 746  
         }
 747  
         */
 748  92
         return retArr;
 749  
     }
 750  
 
 751  
     public void restoreState(FacesContext context, Object state)
 752  
     {
 753  178
         if (state == null)
 754  
         {
 755  76
             return;
 756  
         }
 757  
 
 758  102
         Object[] serializedState = (Object[]) state;
 759  
         
 760  102
         if (!isInitialStateMarked() && !_fullState.isEmpty())
 761  
         {
 762  40
             _fullState.clear();
 763  40
             if(_deltas != null)
 764  
             {
 765  32
                 _deltas.clear();
 766  
             }
 767  
         }
 768  
 
 769  218
         for (int cnt = 0; cnt < serializedState.length; cnt += 2)
 770  
         {
 771  116
             Serializable key = (Serializable) serializedState[cnt];
 772  116
             Object savedValue = UIComponentBase.restoreAttachedState(context,
 773  
                     serializedState[cnt + 1]);
 774  
 
 775  116
             if (isInitialStateMarked())
 776  
             {
 777  64
                 if (savedValue instanceof InternalDeltaListMap)
 778  
                 {
 779  14
                     for (Map.Entry<Object, Boolean> mapEntry : ((Map<Object, Boolean>) savedValue)
 780  
                             .entrySet())
 781  
                     {
 782  24
                         boolean addOrRemove = mapEntry.getValue();
 783  24
                         if (addOrRemove)
 784  
                         {
 785  
                             //add
 786  12
                             this.add(key, mapEntry.getKey());
 787  
                         }
 788  
                         else
 789  
                         {
 790  
                             //remove
 791  12
                             this.remove(key, mapEntry.getKey());
 792  
                         }
 793  24
                     }
 794  
                 }
 795  50
                 else if (savedValue instanceof InternalMap)
 796  
                 {
 797  26
                     for (Map.Entry<String, Object> mapEntry : ((Map<String, Object>) savedValue)
 798  
                             .entrySet())
 799  
                     {
 800  36
                         this.put(key, mapEntry.getKey(), mapEntry.getValue());
 801  36
                     }
 802  
                 }
 803  
                 /*
 804  
                 else if (savedValue instanceof _AttachedDeltaWrapper)
 805  
                 {
 806  
                     _AttachedStateWrapper wrapper = (_AttachedStateWrapper) savedValue;
 807  
                     //Restore delta state
 808  
                     ((PartialStateHolder)_fullState.get(key)).restoreState(context, wrapper.getWrappedStateObject());
 809  
                     //Add this key as StateHolder key 
 810  
                     _stateHolderKeys.add(key);
 811  
                 }
 812  
                 */
 813  
                 else
 814  
                 {
 815  24
                     put(key, savedValue);
 816  
                 }
 817  
             }
 818  
             else
 819  
             {
 820  52
                 put(key, savedValue);
 821  
             }
 822  
         }
 823  102
     }
 824  
     
 825  
     /**
 826  
      * Try to reset the state and then check if the reset was succesful or not,
 827  
      * calling saveState().
 828  
      */
 829  
     public Object resetHardState(FacesContext context)
 830  
     {
 831  0
         if (_transientState != null)
 832  
         {
 833  0
             _transientState.clear();
 834  
         }
 835  0
         if (_deltas != null && !_deltas.isEmpty() && isInitialStateMarked())
 836  
         {
 837  0
             clearFullStateMap(context);
 838  
         }
 839  0
         return saveState(context);
 840  
     }
 841  
     
 842  
     /**
 843  
      * Execute a "soft reset", which means only remove all transient state.
 844  
      */
 845  
     public Object resetSoftState(FacesContext context)
 846  
     {
 847  0
         if (_transientState != null)
 848  
         {
 849  0
             _transientState.clear();
 850  
         }
 851  0
         return null;
 852  
     }
 853  
     
 854  
     protected void clearFullStateMap(FacesContext context)
 855  
     {
 856  0
         if (_deltas != null)
 857  
         {
 858  0
             _deltas.clear();
 859  
         }
 860  0
         if (_initialFullState != null)
 861  
         {
 862  
             // If there is no delta, fullState is not required to be cleared.
 863  0
             _fullState.clear();
 864  0
             copyMap(context, _initialFullState, _fullState);
 865  
         }
 866  0
         if (_initialState != null)
 867  
         {
 868  
             // If initial state is defined, override properties in _initialFullState.
 869  0
             for (int i = 0; i < _initialState.length; i+=2)
 870  
             {
 871  0
                 Serializable key2 = (Serializable) _initialState[i];
 872  0
                 Object defaultValue = _initialState[i+1];
 873  0
                 if (_fullState.containsKey(key2))
 874  
                 {
 875  0
                     _fullState.put(key2, defaultValue);
 876  
                 }
 877  
             }
 878  
         }
 879  0
     }
 880  
 
 881  
     public void setTransient(boolean transientValue)
 882  
     {
 883  2
         _transient = transientValue;
 884  2
     }
 885  
 
 886  
     //We use our own data structures just to make sure
 887  
     //nothing gets mixed up internally
 888  
     static class InternalMap<K, V> extends HashMap<K, V> implements StateHolder
 889  
     {
 890  
         public InternalMap()
 891  
         {
 892  332
             super();
 893  332
         }
 894  
 
 895  
         public InternalMap(int initialCapacity, float loadFactor)
 896  
         {
 897  0
             super(initialCapacity, loadFactor);
 898  0
         }
 899  
 
 900  
         public InternalMap(Map<? extends K, ? extends V> m)
 901  
         {
 902  0
             super(m);
 903  0
         }
 904  
 
 905  
         public InternalMap(int initialSize)
 906  
         {
 907  36
             super(initialSize);
 908  36
         }
 909  
 
 910  
         public boolean isTransient()
 911  
         {
 912  72
             return false;
 913  
         }
 914  
 
 915  
         public void setTransient(boolean newTransientValue)
 916  
         {
 917  
             // No op
 918  0
         }
 919  
 
 920  
         public void restoreState(FacesContext context, Object state)
 921  
         {
 922  94
             Object[] listAsMap = (Object[]) state;
 923  210
             for (int cnt = 0; cnt < listAsMap.length; cnt += 2)
 924  
             {
 925  116
                 this.put((K) listAsMap[cnt], (V) UIComponentBase
 926  
                         .restoreAttachedState(context, listAsMap[cnt + 1]));
 927  
             }
 928  94
         }
 929  
 
 930  
         public Object saveState(FacesContext context)
 931  
         {
 932  72
             int cnt = 0;
 933  72
             Object[] mapArr = new Object[this.size() * 2];
 934  72
             for (Map.Entry<K, V> entry : this.entrySet())
 935  
             {
 936  96
                 mapArr[cnt] = entry.getKey();
 937  96
                 Object value = entry.getValue();
 938  
                 
 939  96
                 if (value instanceof StateHolder ||
 940  
                     value instanceof List ||
 941  
                     !(value instanceof Serializable))
 942  
                 {
 943  8
                     mapArr[cnt + 1] = UIComponentBase.saveAttachedState(context, value);
 944  
                 }
 945  
                 else
 946  
                 {
 947  88
                     mapArr[cnt + 1] = value;
 948  
                 }
 949  96
                 cnt += 2;
 950  96
             }
 951  72
             return mapArr;
 952  
         }
 953  
     }
 954  
 
 955  
     /**
 956  
      * Map used to keep track of list changes 
 957  
      */
 958  
     static class InternalDeltaListMap<K, V> extends InternalMap<K, V>
 959  
     {
 960  
 
 961  
         public InternalDeltaListMap()
 962  
         {
 963  14
             super();
 964  14
         }
 965  
 
 966  
         public InternalDeltaListMap(int initialCapacity, float loadFactor)
 967  
         {
 968  0
             super(initialCapacity, loadFactor);
 969  0
         }
 970  
 
 971  
         public InternalDeltaListMap(int initialSize)
 972  
         {
 973  36
             super(initialSize);
 974  36
         }
 975  
 
 976  
         public InternalDeltaListMap(Map<? extends K, ? extends V> m)
 977  
         {
 978  0
             super(m);
 979  0
         }
 980  
     }
 981  
 
 982  
     static class InternalList<T> extends ArrayList<T> implements StateHolder
 983  
     {
 984  
         public InternalList()
 985  
         {
 986  22
             super();
 987  22
         }
 988  
 
 989  
         public InternalList(Collection<? extends T> c)
 990  
         {
 991  0
             super(c);
 992  0
         }
 993  
 
 994  
         public InternalList(int initialSize)
 995  
         {
 996  44
             super(initialSize);
 997  44
         }
 998  
 
 999  
         public boolean isTransient()
 1000  
         {
 1001  24
             return false;
 1002  
         }
 1003  
 
 1004  
         public void setTransient(boolean newTransientValue)
 1005  
         {
 1006  0
         }
 1007  
 
 1008  
         public void restoreState(FacesContext context, Object state)
 1009  
         {
 1010  22
             Object[] listAsArr = (Object[]) state;
 1011  
             //since all other options would mean dual iteration 
 1012  
             //we have to do it the hard way
 1013  44
             for (Object elem : listAsArr)
 1014  
             {
 1015  22
                 add((T) UIComponentBase.restoreAttachedState(context, elem));
 1016  
             }
 1017  22
         }
 1018  
 
 1019  
         public Object saveState(FacesContext context)
 1020  
         {
 1021  24
             Object[] values = new Object[size()];
 1022  48
             for (int i = 0; i < size(); i++)
 1023  
             {
 1024  24
                 Object value = get(i);
 1025  
                 
 1026  24
                 if (value instanceof StateHolder ||
 1027  
                     value instanceof List ||
 1028  
                     !(value instanceof Serializable))
 1029  
                 {
 1030  0
                     values[i] = UIComponentBase.saveAttachedState(context, value);
 1031  
                 }
 1032  
                 else
 1033  
                 {
 1034  24
                     values[i] = value;
 1035  
                 }                
 1036  
             }
 1037  24
             return values;
 1038  
         }
 1039  
     }
 1040  
 
 1041  
     public Object getTransient(Object key)
 1042  
     {
 1043  8
         return (_transientState == null) ? null : _transientState.get(key);
 1044  
     }
 1045  
 
 1046  
     public Object getTransient(Object key, Object defaultValue)
 1047  
     {
 1048  0
         Object returnValue = (_transientState == null) ? null : _transientState.get(key);
 1049  0
         if (returnValue != null)
 1050  
         {
 1051  0
             return returnValue;
 1052  
         }
 1053  0
         return defaultValue;
 1054  
     }
 1055  
 
 1056  
     public Object putTransient(Object key, Object value)
 1057  
     {
 1058  8
         if (_transientState == null)
 1059  
         {
 1060  8
             _transientState = new HashMap<Object, Object>();
 1061  
         }
 1062  8
         return _transientState.put(key, value);
 1063  
     }
 1064  
 
 1065  
     @SuppressWarnings("unchecked")
 1066  
     public void restoreTransientState(FacesContext context, Object state)
 1067  
     {
 1068  176
         _transientState = (Map<Object, Object>) state;
 1069  176
     }
 1070  
     
 1071  
     public Object saveTransientState(FacesContext context)
 1072  
     {
 1073  176
         return _transientState;
 1074  
     }
 1075  
 
 1076  
     public void markPropertyInInitialState(Object[] defaultInitialState)
 1077  
     {
 1078  
         // Check if in the fullState, one of the default properties were changed
 1079  26
         boolean canApplyDefaultInitialState = true;
 1080  130
         for (int i = 0; i < defaultInitialState.length; i+=2)
 1081  
         {
 1082  104
             Serializable key = (Serializable) defaultInitialState[i];
 1083  104
             if (_fullState.containsKey(key))
 1084  
             {
 1085  0
                 canApplyDefaultInitialState = false;
 1086  0
                 break;
 1087  
             }
 1088  
         }
 1089  26
         if (canApplyDefaultInitialState)
 1090  
         {
 1091  
             // Most of the times the defaultInitialState is used.
 1092  26
             _initialState = defaultInitialState;
 1093  
         }
 1094  
         else
 1095  
         {
 1096  
             // recalculate it
 1097  0
             Object[] initialState = new Object[defaultInitialState.length];
 1098  0
             for (int i = 0; i < defaultInitialState.length; i+=2)
 1099  
             {
 1100  0
                 Serializable key = (Serializable) defaultInitialState[i];
 1101  0
                 initialState[i] = key;
 1102  0
                 if (_fullState.containsKey(key))
 1103  
                 {
 1104  0
                     initialState[i+1] = _fullState.get(key);
 1105  
                 }
 1106  
                 else
 1107  
                 {
 1108  0
                     initialState[i+1] = defaultInitialState[i+1];
 1109  
                 }
 1110  
             }
 1111  0
             _initialState = initialState;
 1112  
         }
 1113  26
     }
 1114  
 }