All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.myfaces.trinidad.bean.util.PropertyHashMap Maven / Gradle / Ivy

There is a newer version: 2.2.1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.myfaces.trinidad.bean.util;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.el.ValueExpression;

import javax.faces.component.PartialStateHolder;
import javax.faces.context.FacesContext;

import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.bean.PropertyKey;
import org.apache.myfaces.trinidad.bean.PropertyMap;


public class PropertyHashMap extends HashMap
                             implements PropertyMap
{
  public PropertyHashMap(
    PropertyMap map)
  {
    super(map);
  }

  public PropertyHashMap(
    int   initialCapacity,
    float loadFactor)
  {
    super(initialCapacity, loadFactor);
 }

  public PropertyHashMap(
    int initialCapacity)
  {
    super(initialCapacity);
  }

  public PropertyHashMap()
  {
    super();
  }

  @Override
   public Object put(
     PropertyKey key,
     Object      value)
   {
     Object retValue = super.put(key, value);
     if (_createDeltas())
     {
       
       if ( key.getMutable().isAtLeastSometimesMutable() || !_equals(value, retValue))
         _deltas.put(key, value);
     }
     else if (key.getMutable().isAtLeastSometimesMutable() && !(value instanceof ValueExpression))
     {
       _getMutableTracker(true).addProperty(key);
     }
     
     if (key.isPartialStateHolder())
     {
       _getPartialStateHolderTracker(true).addProperty(key);
     }

     return retValue;
   }

  @Override
   public Object remove(
     Object key)
   {
     boolean useDeltas = _createDeltas();
    
     if (useDeltas)
     {
       if (!super.containsKey(key))
         return null;

       // If this key is contained, it certainly must be a PropertyKey!
       assert(key instanceof PropertyKey);
       _deltas.put((PropertyKey) key, null);
     }
     
     if (key instanceof PropertyKey)
     {
       PropertyKey propKey  = (PropertyKey)key;
       if (propKey.isPartialStateHolder())
       {
         _getPartialStateHolderTracker(true).removeProperty(propKey);
       }
       
       if (!useDeltas &&  propKey.getMutable().isAtLeastSometimesMutable())
       {
         PropertyTracker mutableTracker = _getMutableTracker(false);
         
         if (mutableTracker != null)
           mutableTracker.removeProperty(propKey);
       }
     }

     return super.remove(key);
   }

  @Override
  public void putAll(Map t)
  {
    boolean useDeltas =_createDeltas();
    
    if (useDeltas)
      _deltas.putAll(t);

    Set keys = t.keySet();
    for (PropertyKey key: keys)
    {
      if (key.isPartialStateHolder())
      {
        _getPartialStateHolderTracker(true).addProperty(key);
      }  
      
      if (!useDeltas && key.getMutable().isAtLeastSometimesMutable())
      {
        Object value = t.get(key);
        
        if (!(value instanceof ValueExpression))
        {
          _getMutableTracker(true).addProperty(key);
        }
      }

    }

    super.putAll(t);
  }

  public Object saveState(FacesContext context)
  {
    if (_initialStateMarked)
    {    
      if (_deltas == null)
      {
        // if deltas is null still call _createDeltaPropertyMap but pass in false in case there
        // are mutable or partialStateHolder attributes
        _deltas = _createDeltaPropertyMap(false);
      }
      
      if (_deltas == null)
        return null;

      return StateUtils.saveState(_deltas, context, getUseStateHolder());
    }
    else
    {
      return StateUtils.saveState(this, context, getUseStateHolder());
    }
  }

  public void restoreState(
    FacesContext context,
    FacesBean.Type type,
    Object state)
  {
    StateUtils.restoreState(this, context, type, state, getUseStateHolder());
  }

  protected PropertyMap createDeltaPropertyMap()
  {
    return _createDeltaPropertyMap(true);
  }
  
  /**
   *
   * @param createAlways if createAlways is true then always create the map. 
   *        If createAlways is false then only create the map if one of the trackers are empty
   */
  private PropertyMap _createDeltaPropertyMap(boolean createAlways)
  {  
    PropertyTracker tracker = _getMutableTracker(false);
    PropertyTracker partialTracker = _getPartialStateHolderTracker(false);    
   
    // if createAlways is true then always create the map.
    // if createAlways is false then only create the map if one of the trackers are empty
    if (createAlways || tracker != null || partialTracker != null)
    {
      PropertyHashMap map = new PropertyHashMap(2);
      map.setUseStateHolder(getUseStateHolder());
      map.setType(_type);
        
      if (tracker != null)
      {      
        for (PropertyKey key: tracker)
        {
          Object val = get(key);
          
          if (val != null)
          {
            map.put(key, val);
          }
        }
        
        _mutableTracker = null;
      }
  
      
      if (partialTracker != null)
      {      
        for (PropertyKey key: partialTracker)
        {
          // the key might have been in the mutable tracker, so check if the map already contains the key          
          if(!map.containsKey(key))
          {
            Object val = get(key);
            
            if (val != null)
            {
              map.put(key, val);
            }
          }
        }    
      }
      
      return map;
    }
    
    return null;
  }

  public boolean getUseStateHolder()
  {
    return _useStateHolder;
  }

  public void setUseStateHolder(boolean useStateHolder)
  {
    _useStateHolder = useStateHolder;
  }

  // =-=AEW CLEAR?

  public void markInitialState()
  {
    _initialStateMarked = true;
    
    // PropertyTracker uses a bitmask to track properties
    // We are tracking all properties that have CA_PARTIAL_STATE_HOLDER capability,
    // so that we do not have to check every property here
    PropertyTracker tracker = _getPartialStateHolderTracker(false);
    if (tracker != null)
    {
      for (PropertyKey key: tracker)
      {
        Object val = get(key);
        if (val != null)
        {
          ((PartialStateHolder)val).markInitialState();
        }
      }
    }
  }

  public void clearInitialState()
  {
    _initialStateMarked = false;
    _deltas = null;
    
    // PropertyTracker uses a bitmask to track properties
    // We are tracking all properties that have CA_PARTIAL_STATE_HOLDER capability,
    // so that we do not have to check every property here
    PropertyTracker tracker = _getPartialStateHolderTracker(false);
    if (tracker != null)
    {
      for (PropertyKey key: tracker)
      {
        Object val = get(key);
        if (val != null)
        {
          ((PartialStateHolder)val).clearInitialState();
        }
      }
    }
  }

  public boolean initialStateMarked()
  {
    return _initialStateMarked;
  }
  
  /**
   * Sets the the FacesBean type used by this map's owner bean
   * @param type FacesBean type
   */
  public void setType(FacesBean.Type type)
  {
    _type = type;
  }

  private boolean _createDeltas()
  {
    if (_initialStateMarked)
    {
      if (_deltas == null)
      {
        _deltas = createDeltaPropertyMap();
      }

      return true;
    }

    return false;
  }

  static private boolean _equals(Object a, Object b)
  {
    if (a == b)
      return true;

    if (a == null)
      return false;

    return a.equals(b);
  }
  
  private PropertyTracker _getPartialStateHolderTracker(boolean create)
  {
    if (_tracker == null && create)
    {
      if (_type == null)
      {
        throw new IllegalStateException("FacesBean.TYPE is required to track properties");
      }
      _tracker = new PropertyTracker(_type);
    }
    return _tracker;                  
  }
  
  
  private PropertyTracker _getMutableTracker(boolean create)
  {
    if (_mutableTracker == null && create)
    {
      if (_type == null)
      {
        throw new IllegalStateException("FacesBean.TYPE is required to track properties");
      }
      _mutableTracker = new PropertyTracker(_type);
    }
    return _mutableTracker;                  
  }  

  private transient boolean _initialStateMarked;
  private transient PropertyMap _deltas;
  private boolean      _useStateHolder;
  private transient FacesBean.Type _type;
  private transient PropertyTracker _tracker;
  private transient PropertyTracker _mutableTracker;

  private static final long serialVersionUID = 1L;

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy