Coverage Report - org.apache.myfaces.view.facelets.tag.composite.CompositeComponentBeanInfo
 
Classes in this File Line Coverage Branch Coverage Complexity
CompositeComponentBeanInfo
0%
0/77
0%
0/40
2.286
CompositeComponentBeanInfo$PropertyDescriptorMap
0%
0/13
N/A
2.286
 
 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.composite;
 20  
 
 21  
 import java.beans.BeanDescriptor;
 22  
 import java.beans.PropertyDescriptor;
 23  
 import java.beans.SimpleBeanInfo;
 24  
 import java.io.Externalizable;
 25  
 import java.io.IOException;
 26  
 import java.io.ObjectInput;
 27  
 import java.io.ObjectOutput;
 28  
 import java.util.ArrayList;
 29  
 import java.util.Collection;
 30  
 import java.util.Collections;
 31  
 import java.util.Enumeration;
 32  
 import java.util.HashMap;
 33  
 import java.util.List;
 34  
 import java.util.Map;
 35  
 import java.util.Set;
 36  
 
 37  
 import javax.faces.view.AttachedObjectTarget;
 38  
 
 39  
 /**
 40  
  * Implementation of BeanInfo object used by composite components.
 41  
  * Instances of this class are found on component attribute map
 42  
  * using the key UIComponent.BEANINFO_KEY.
 43  
  * 
 44  
  * The points to take into account for implement this class are this:
 45  
  * 
 46  
  * - The following tags:
 47  
  * 
 48  
  *    composite:interface
 49  
  *    composite:attribute
 50  
  *    composite:facet
 51  
  *    composite:valueHolder
 52  
  *    composite:editableValueHolder
 53  
  *    composite:actionSource
 54  
  *    composite:extension
 55  
  *    
 56  
  *    must deal with this class, so it is expected methods that manipulate
 57  
  *    data here are called from their tag handlers.
 58  
  *    
 59  
  * - ViewDeclarationLanguage.retargetAttachedObjects and 
 60  
  *   ViewDeclarationLanguage.retargetMethodExpressions read information
 61  
  *   contained here
 62  
  * 
 63  
  * - This object goes on attribute map, so it is necessary that
 64  
  *   this instance should be Serializable. But note that BeanDescriptor
 65  
  *   is not, so the best way is implements Externalizable interface
 66  
  *   and implement its methods. The only information we need to be Serializable
 67  
  *   from this object is the related to BeanDescriptor, but note that
 68  
  *   serialize information used only in build view time ( like
 69  
  *   AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY list) is not required 
 70  
  *   and could cause serialization exceptions. 
 71  
  * 
 72  
  * @author Leonardo Uribe (latest modification by $Author$)
 73  
  * @version $Revision$ $Date$
 74  
  */
 75  
 public class CompositeComponentBeanInfo extends SimpleBeanInfo 
 76  
     implements Externalizable
 77  
 {
 78  
     
 79  
     public static final String PROPERTY_DESCRIPTOR_MAP_KEY = "oam.cc.beanInfo.PDM";
 80  
 
 81  
     /**
 82  
      * Most of the information here are filled on composite:interface tag.
 83  
      * It is also expected that AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY
 84  
      * key is used by other handlers inside the inner map for this BeanDescriptor.
 85  
      */
 86  
     private BeanDescriptor _descriptor;
 87  
     
 88  
     /**
 89  
      * ViewDeclarationLanguage.retargetMethodExpressions algorithm
 90  
      * suggest that every attribute should have a PropertyDescriptor
 91  
      * object defined for it. So, this list is expected to be filled
 92  
      * on composite:attribute tag. This list is used only when
 93  
      * retargetAttachedObjects and retargetAttachedMethodExpressions,
 94  
      * and this methods are called only on buildView time, so
 95  
      * we don't need to Serialize this list. 
 96  
      */
 97  
     private List<PropertyDescriptor> _propertyDescriptors;
 98  
     
 99  0
     private static final PropertyDescriptor[] EMPTY_PROPERTY_DESCRIPTOR_ARRAY = new PropertyDescriptor[0];
 100  
     
 101  
     private PropertyDescriptor[] _propertyDescriptorsArray;
 102  
     
 103  
     private Map<String, PropertyDescriptor> _propertyDescriptorsMap;
 104  
     
 105  
     /**
 106  
      * Used for Serialization
 107  
      */
 108  
     public CompositeComponentBeanInfo()
 109  
     {
 110  0
         super();
 111  0
     }
 112  
     
 113  
     public CompositeComponentBeanInfo(BeanDescriptor descriptor)
 114  
     {
 115  0
         super();
 116  0
         _descriptor = descriptor;
 117  0
         getBeanDescriptor().setValue(PROPERTY_DESCRIPTOR_MAP_KEY, new PropertyDescriptorMap());
 118  0
     }
 119  
     
 120  
     @Override
 121  
     public BeanDescriptor getBeanDescriptor()
 122  
     {
 123  0
         return _descriptor;
 124  
     }
 125  
 
 126  
     @Override
 127  
     public PropertyDescriptor[] getPropertyDescriptors()
 128  
     {
 129  0
         if (_propertyDescriptors == null)
 130  
         {
 131  0
             return EMPTY_PROPERTY_DESCRIPTOR_ARRAY;
 132  
         }
 133  
         else
 134  
         {
 135  0
             if (_propertyDescriptorsArray == null)
 136  
             {
 137  0
                 _propertyDescriptorsArray = _propertyDescriptors.toArray(
 138  
                         new PropertyDescriptor[_propertyDescriptors.size()]); 
 139  
             }
 140  0
             else if (_propertyDescriptorsArray.length != _propertyDescriptors.size())
 141  
             {
 142  0
                 _propertyDescriptorsArray = _propertyDescriptors.toArray(
 143  
                         new PropertyDescriptor[_propertyDescriptors.size()]);
 144  
             }
 145  0
             return _propertyDescriptorsArray; 
 146  
         }
 147  
     }
 148  
 
 149  
     public List<PropertyDescriptor> getPropertyDescriptorsList()
 150  
     {
 151  0
         if (_propertyDescriptors == null)
 152  
         {
 153  0
             _propertyDescriptors = new ArrayList<PropertyDescriptor>();
 154  
         }
 155  0
         return _propertyDescriptors;
 156  
     }
 157  
 
 158  
     public void setPropertyDescriptorsList(List<PropertyDescriptor> descriptors)
 159  
     {
 160  0
         _propertyDescriptors = descriptors;
 161  0
     }
 162  
 
 163  
     public void readExternal(ObjectInput in) throws IOException,
 164  
             ClassNotFoundException
 165  
     {
 166  0
         Class beanClass = (Class) in.readObject();
 167  0
         Class customizerClass = (Class) in.readObject();
 168  0
         if (customizerClass == null)
 169  
         {
 170  0
             _descriptor = new BeanDescriptor(beanClass);
 171  
         }
 172  
         else
 173  
         {
 174  0
             _descriptor = new BeanDescriptor(beanClass, customizerClass);
 175  
         }
 176  0
         _descriptor.setDisplayName((String) in.readObject());
 177  0
         _descriptor.setExpert(in.readBoolean());
 178  0
         _descriptor.setName((String) in.readObject());
 179  0
         _descriptor.setPreferred(in.readBoolean());
 180  0
         _descriptor.setShortDescription((String) in.readObject());
 181  0
         _descriptor.setValue(PROPERTY_DESCRIPTOR_MAP_KEY, new PropertyDescriptorMap());
 182  
         
 183  0
         Map<String,Object> map = (Map) in.readObject();
 184  
         
 185  0
         for (Map.Entry<String, Object> entry : map.entrySet())
 186  
         {
 187  0
             _descriptor.setValue(entry.getKey(), entry.getValue());
 188  0
         }
 189  0
         _propertyDescriptors = (List<PropertyDescriptor>) in.readObject();
 190  0
     }
 191  
 
 192  
     public void writeExternal(ObjectOutput out) throws IOException
 193  
     {
 194  0
         out.writeObject(_descriptor.getBeanClass());
 195  0
         out.writeObject(_descriptor.getCustomizerClass());
 196  0
         out.writeObject(_descriptor.getDisplayName());
 197  0
         out.writeBoolean(_descriptor.isExpert());
 198  0
         out.writeObject(_descriptor.getName());
 199  0
         out.writeBoolean(_descriptor.isPreferred());
 200  0
         out.writeObject(_descriptor.getShortDescription());
 201  
         
 202  0
         Map<String,Object> map = new HashMap<String, Object>(4,1);
 203  
         
 204  0
         for (Enumeration<String> e = _descriptor.attributeNames(); e.hasMoreElements();)
 205  
         {
 206  0
             String name = e.nextElement();
 207  
             
 208  
             // It is not necessary to serialize AttachedObjectTarget list because
 209  
             // we only use it when VDL.retargetAttachedObjects() is called and this only
 210  
             // happen when the view is built. Also, try to serialize this instances could
 211  
             // cause unwanted exceptions.
 212  0
             if (!AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY.equals(name) &&
 213  
                 !PROPERTY_DESCRIPTOR_MAP_KEY.equals(name))
 214  
             {
 215  0
                 map.put(name, _descriptor.getValue(name));
 216  
             }
 217  0
         }
 218  0
         out.writeObject(map);
 219  0
         out.writeObject(_propertyDescriptors);
 220  
         
 221  0
     }
 222  
     
 223  
     public Map<String, PropertyDescriptor> getPropertyDescriptorsMap()
 224  
     {
 225  0
         if (_propertyDescriptors == null)
 226  
         {
 227  0
             return Collections.emptyMap();
 228  
         }
 229  
         else
 230  
         {
 231  0
             if (_propertyDescriptors.isEmpty())
 232  
             {
 233  0
                 return Collections.emptyMap();
 234  
             }
 235  0
             else if (_propertyDescriptorsMap == null)
 236  
             {
 237  0
                 int initCapacity = (_propertyDescriptors.size() * 4 + 3) / 3;
 238  0
                 _propertyDescriptorsMap = new HashMap<String, PropertyDescriptor>(initCapacity);
 239  0
                 for (PropertyDescriptor p : _propertyDescriptors)
 240  
                 {
 241  0
                     if (!_propertyDescriptorsMap.containsKey(p.getName()))
 242  
                     {
 243  0
                         _propertyDescriptorsMap.put(p.getName(), p);
 244  
                     }
 245  0
                 }
 246  0
             }
 247  0
             else if (_propertyDescriptorsMap.size() != _propertyDescriptors.size())
 248  
             {
 249  0
                 for (PropertyDescriptor p : _propertyDescriptors)
 250  
                 {
 251  0
                     if (!_propertyDescriptorsMap.containsKey(p.getName()))
 252  
                     {
 253  0
                         _propertyDescriptorsMap.put(p.getName(), p);
 254  
                     }
 255  0
                 }
 256  0
                 if (_propertyDescriptorsMap.size() != _propertyDescriptors.size())
 257  
                 {
 258  
                     // PropertyDescriptor was removed
 259  0
                     _propertyDescriptorsMap.clear();
 260  0
                     for (PropertyDescriptor p : _propertyDescriptors)
 261  
                     {
 262  0
                         if (!_propertyDescriptorsMap.containsKey(p.getName()))
 263  
                         {
 264  0
                             _propertyDescriptorsMap.put(p.getName(), p);
 265  
                         }
 266  0
                     }
 267  
                 }
 268  
             }
 269  0
             return _propertyDescriptorsMap;
 270  
         }
 271  
     }
 272  
     
 273  
     /**
 274  
      * Read only map for fast access. It works as an indirection over the real list.
 275  
      */
 276  0
     public class PropertyDescriptorMap implements Map<String, PropertyDescriptor>
 277  
     {
 278  
         
 279  
         public int size()
 280  
         {
 281  0
             return getPropertyDescriptorsMap().size();
 282  
         }
 283  
 
 284  
         public boolean isEmpty()
 285  
         {
 286  0
             return getPropertyDescriptorsMap().isEmpty();
 287  
         }
 288  
 
 289  
        
 290  
         public boolean containsKey(Object key)
 291  
         {
 292  0
             return getPropertyDescriptorsMap().containsKey(key);
 293  
         }
 294  
 
 295  
         public boolean containsValue(Object value)
 296  
         {
 297  0
             return getPropertyDescriptorsMap().containsValue(value);
 298  
         }
 299  
 
 300  
         public PropertyDescriptor get(Object key)
 301  
         {
 302  0
             return getPropertyDescriptorsMap().get(key);
 303  
         }
 304  
 
 305  
         public PropertyDescriptor put(String key, PropertyDescriptor value)
 306  
         {
 307  0
             throw new UnsupportedOperationException();
 308  
         }
 309  
 
 310  
         public PropertyDescriptor remove(Object key)
 311  
         {
 312  0
             throw new UnsupportedOperationException();
 313  
         }
 314  
 
 315  
         public void putAll(Map<? extends String, ? extends PropertyDescriptor> m)
 316  
         {
 317  0
             throw new UnsupportedOperationException();
 318  
         }
 319  
 
 320  
         public void clear()
 321  
         {
 322  0
             throw new UnsupportedOperationException();
 323  
         }
 324  
 
 325  
         public Set<String> keySet()
 326  
         {
 327  0
             return getPropertyDescriptorsMap().keySet();
 328  
         }
 329  
 
 330  
         public Collection<PropertyDescriptor> values()
 331  
         {
 332  0
             return getPropertyDescriptorsMap().values();
 333  
         }
 334  
 
 335  
         public Set<Entry<String, PropertyDescriptor>> entrySet()
 336  
         {
 337  0
             return getPropertyDescriptorsMap().entrySet();
 338  
         }
 339  
     }
 340  
 }