Coverage Report - net.sf.ezmorph.bean.MorphDynaBean
 
Classes in this File Line Coverage Branch Coverage Complexity
MorphDynaBean
96%
151/157
75%
169/224
3.042
 
 1  
 /*
 2  
  * Copyright 2006-2007-2007 the original author or authors.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package net.sf.ezmorph.bean;
 18  
 
 19  
 import java.io.Serializable;
 20  
 import java.lang.reflect.Array;
 21  
 import java.util.ArrayList;
 22  
 import java.util.HashMap;
 23  
 import java.util.List;
 24  
 import java.util.Map;
 25  
 
 26  
 import net.sf.ezmorph.MorphException;
 27  
 import net.sf.ezmorph.MorphUtils;
 28  
 import net.sf.ezmorph.MorpherRegistry;
 29  
 
 30  
 import org.apache.commons.beanutils.DynaBean;
 31  
 import org.apache.commons.beanutils.DynaClass;
 32  
 import org.apache.commons.beanutils.DynaProperty;
 33  
 import org.apache.commons.lang.builder.EqualsBuilder;
 34  
 import org.apache.commons.lang.builder.HashCodeBuilder;
 35  
 import org.apache.commons.lang.builder.ToStringBuilder;
 36  
 import org.apache.commons.lang.builder.ToStringStyle;
 37  
 
 38  
 /**
 39  
  * @author Andres Almiray <aalmiray@users.sourceforge.net>
 40  
  */
 41  
 public final class MorphDynaBean implements DynaBean, Serializable
 42  
 {
 43  
    private static final long serialVersionUID = -605547389232706344L;
 44  
    private MorphDynaClass dynaClass;
 45  211
    private Map dynaValues = new HashMap();
 46  
    private MorpherRegistry morpherRegistry;
 47  
 
 48  
    public MorphDynaBean()
 49  
    {
 50  211
       this( null );
 51  211
    }
 52  
 
 53  159
    public MorphDynaBean( MorpherRegistry morpherRegistry )
 54  52
    {
 55  211
       setMorpherRegistry( morpherRegistry );
 56  211
    }
 57  
 
 58  
    public boolean contains( String name, String key )
 59  
    {
 60  20
       DynaProperty dynaProperty = getDynaProperty( name );
 61  
 
 62  20
       Class type = dynaProperty.getType();
 63  30
       if( !Map.class.isAssignableFrom( type ) ){
 64  4
          throw new MorphException( "Non-Mapped property name: " + name + " key: " + key );
 65  
       }
 66  
 
 67  16
       Object value = dynaValues.get( name );
 68  16
       if( value == null ){
 69  4
          value = new HashMap();
 70  4
          dynaValues.put( name, value );
 71  
       }
 72  16
       return ((Map) value).containsKey( key );
 73  
    }
 74  
 
 75  
    public boolean equals( Object obj )
 76  
    {
 77  16
       if( this == obj ){
 78  4
          return true;
 79  
       }
 80  
 
 81  12
       if( obj == null ){
 82  4
          return false;
 83  
       }
 84  
 
 85  8
       if( !(obj instanceof MorphDynaBean) ){
 86  4
          return false;
 87  
       }
 88  
 
 89  4
       MorphDynaBean other = (MorphDynaBean) obj;
 90  4
       EqualsBuilder builder = new EqualsBuilder().append( this.dynaClass, other.dynaClass );
 91  4
       DynaProperty[] props = dynaClass.getDynaProperties();
 92  56
       for( int i = 0; i < props.length; i++ ){
 93  52
          DynaProperty prop = props[i];
 94  52
          builder.append( dynaValues.get( prop.getName() ), dynaValues.get( prop.getName() ) );
 95  
       }
 96  4
       return builder.isEquals();
 97  
    }
 98  
 
 99  
    public Object get( String name )
 100  
    {
 101  138
       Object value = dynaValues.get( name );
 102  
 
 103  138
       if( value != null ){
 104  130
          return value;
 105  
       }
 106  
 
 107  8
       Class type = getDynaProperty( name ).getType();
 108  4
       if( !type.isPrimitive() ){
 109  4
          return value;
 110  
       }else{
 111  0
          return morpherRegistry.morph( type, value );
 112  
       }
 113  
    }
 114  
 
 115  
    public Object get( String name, int index )
 116  
    {
 117  20
       DynaProperty dynaProperty = getDynaProperty( name );
 118  
 
 119  20
       Class type = dynaProperty.getType();
 120  20
       if( !type.isArray() && !List.class.isAssignableFrom( type ) ){
 121  4
          throw new MorphException( "Non-Indexed property name: " + name + " index: " + index );
 122  
       }
 123  
 
 124  16
       Object value = dynaValues.get( name );
 125  
 
 126  16
       if( value.getClass()
 127  12
             .isArray() ){
 128  8
          value = Array.get( value, index );
 129  8
       }else if( value instanceof List ){
 130  8
          value = ((List) value).get( index );
 131  
       }
 132  
 
 133  16
       return value;
 134  
    }
 135  
 
 136  
    public Object get( String name, String key )
 137  
    {
 138  12
       DynaProperty dynaProperty = getDynaProperty( name );
 139  
 
 140  12
       Class type = dynaProperty.getType();
 141  12
       if( !Map.class.isAssignableFrom( type ) ){
 142  4
          throw new MorphException( "Non-Mapped property name: " + name + " key: " + key );
 143  
       }
 144  
 
 145  8
       Object value = dynaValues.get( name );
 146  8
       if( value == null ){
 147  4
          value = new HashMap();
 148  4
          dynaValues.put( name, value );
 149  
       }
 150  8
       return ((Map) value).get( key );
 151  
    }
 152  
 
 153  
    public DynaClass getDynaClass()
 154  
    {
 155  2171
       return this.dynaClass;
 156  
    }
 157  
 
 158  
    public MorpherRegistry getMorpherRegistry()
 159  
    {
 160  0
       return morpherRegistry;
 161  
    }
 162  
 
 163  
    public int hashCode()
 164  
    {
 165  16
       HashCodeBuilder builder = new HashCodeBuilder().append( dynaClass );
 166  16
       DynaProperty[] props = dynaClass.getDynaProperties();
 167  204
       for( int i = 0; i < props.length; i++ ){
 168  188
          DynaProperty prop = props[i];
 169  188
          builder.append( dynaValues.get( prop.getName() ) );
 170  
       }
 171  16
       return builder.toHashCode();
 172  
    }
 173  
 
 174  
    public void remove( String name, String key )
 175  
    {
 176  8
       DynaProperty dynaProperty = getDynaProperty( name );
 177  
 
 178  8
       Class type = dynaProperty.getType();
 179  8
       if( !Map.class.isAssignableFrom( type ) ){
 180  4
          throw new MorphException( "Non-Mapped property name: " + name + " key: " + key );
 181  
       }
 182  
 
 183  4
       Object value = dynaValues.get( name );
 184  4
       if( value == null ){
 185  0
          value = new HashMap();
 186  0
          dynaValues.put( name, value );
 187  
       }
 188  4
       ((Map) value).remove( key );
 189  4
    }
 190  
 
 191  
    public void set( String name, int index, Object value )
 192  
    {
 193  20
       DynaProperty dynaProperty = getDynaProperty( name );
 194  
 
 195  20
       Class type = dynaProperty.getType();
 196  20
       if( !type.isArray() && !List.class.isAssignableFrom( type ) ){
 197  4
          throw new MorphException( "Non-Indexed property name: " + name + " index: " + index );
 198  
       }
 199  
 
 200  16
       Object prop = dynaValues.get( name );
 201  16
       if( prop == null ){
 202  8
          if( List.class.isAssignableFrom( type ) ){
 203  4
             prop = new ArrayList();
 204  
          }else{
 205  4
             prop = Array.newInstance( type.getComponentType(), index + 1 );
 206  
          }
 207  8
          dynaValues.put( name, prop );
 208  
       }
 209  
 
 210  16
       if( prop.getClass()
 211  12
             .isArray() ){
 212  8
          if( index >= Array.getLength( prop ) ){
 213  4
             Object tmp = Array.newInstance( type.getComponentType(), index + 1 );
 214  4
             System.arraycopy( prop, 0, tmp, 0, Array.getLength( prop ) );
 215  4
             prop = tmp;
 216  4
             dynaValues.put( name, tmp );
 217  
          }
 218  8
          Array.set( prop, index, value );
 219  8
       }else if( prop instanceof List ){
 220  8
          List l = (List) prop;
 221  8
          if( index >= l.size() ){
 222  12
             for( int i = l.size(); i <= index + 1; i++ ){
 223  8
                l.add( null );
 224  
             }
 225  
          }
 226  8
          ((List) prop).set( index, value );
 227  
       }
 228  16
    }
 229  
 
 230  
    public void set( String name, Object value )
 231  
    {
 232  1956
       DynaProperty property = getDynaProperty( name );
 233  
 
 234  1956
       if( value == null || !isDynaAssignable( property.getType(), value.getClass() ) ){
 235  1860
          value = morpherRegistry.morph( property.getType(), value );
 236  
       }
 237  
 
 238  1956
       dynaValues.put( name, value );
 239  1956
    }
 240  
 
 241  
    public void set( String name, String key, Object value )
 242  
    {
 243  16
       DynaProperty dynaProperty = getDynaProperty( name );
 244  
 
 245  16
       Class type = dynaProperty.getType();
 246  16
       if( !Map.class.isAssignableFrom( type ) ){
 247  4
          throw new MorphException( "Non-Mapped property name: " + name + " key: " + key );
 248  
       }
 249  
 
 250  12
       Object prop = dynaValues.get( name );
 251  12
       if( prop == null ){
 252  8
          prop = new HashMap();
 253  8
          dynaValues.put( name, prop );
 254  
       }
 255  12
       ((Map) prop).put( key, value );
 256  12
    }
 257  
 
 258  
    public synchronized void setDynaBeanClass( MorphDynaClass dynaClass )
 259  
    {
 260  218
       if( this.dynaClass == null ){
 261  199
          this.dynaClass = dynaClass;
 262  
       }
 263  218
    }
 264  
 
 265  
    public void setMorpherRegistry( MorpherRegistry morpherRegistry )
 266  
    {
 267  410
       if( morpherRegistry == null ){
 268  211
          this.morpherRegistry = new MorpherRegistry();
 269  211
          MorphUtils.registerStandardMorphers( this.morpherRegistry );
 270  
       }else{
 271  199
          this.morpherRegistry = morpherRegistry;
 272  
       }
 273  410
    }
 274  
 
 275  
    public String toString()
 276  
    {
 277  0
       return new ToStringBuilder( this, ToStringStyle.MULTI_LINE_STYLE ).append( dynaValues )
 278  0
             .toString();
 279  
    }
 280  
 
 281  
    protected DynaProperty getDynaProperty( String name )
 282  
    {
 283  2060
       DynaProperty property = getDynaClass().getDynaProperty( name );
 284  2060
       if( property == null ){
 285  4
          throw new MorphException( "Unspecified property for " + name );
 286  
       }
 287  2056
       return property;
 288  
    }
 289  
 
 290  
    protected boolean isDynaAssignable( Class dest, Class src )
 291  
    {
 292  126
       boolean assignable = dest.isAssignableFrom( src );
 293  126
       if( assignable ){
 294  64
          return true;
 295  
       }
 296  62
       assignable = (dest == Boolean.TYPE && src == Boolean.class) ? true : assignable;
 297  62
       assignable = (dest == Byte.TYPE && src == Byte.class) ? true : assignable;
 298  62
       assignable = (dest == Character.TYPE && src == Character.class) ? true : assignable;
 299  62
       assignable = (dest == Short.TYPE && src == Short.class) ? true : assignable;
 300  62
       assignable = (dest == Integer.TYPE && src == Integer.class) ? true : assignable;
 301  62
       assignable = (dest == Long.TYPE && src == Long.class) ? true : assignable;
 302  62
       assignable = (dest == Float.TYPE && src == Float.class) ? true : assignable;
 303  62
       assignable = (dest == Double.TYPE && src == Double.class) ? true : assignable;
 304  
 
 305  62
       if( src == Double.TYPE || Double.class.isAssignableFrom( src ) ){
 306  7
          assignable = (isByte( dest ) || isShort( dest ) || isInteger( dest ) || isLong( dest ) || isFloat( dest )) ? true
 307  3
                : assignable;
 308  
       }
 309  62
       if( src == Float.TYPE || Float.class.isAssignableFrom( src ) ){
 310  7
          assignable = (isByte( dest ) || isShort( dest ) || isInteger( dest ) || isLong( dest )) ? true
 311  3
                : assignable;
 312  
       }
 313  62
       if( src == Long.TYPE || Long.class.isAssignableFrom( src ) ){
 314  4
          assignable = (isByte( dest ) || isShort( dest ) || isInteger( dest )) ? true : assignable;
 315  
       }
 316  62
       if( src == Integer.TYPE || Integer.class.isAssignableFrom( src ) ){
 317  4
          assignable = (isByte( dest ) || isShort( dest )) ? true : assignable;
 318  
       }
 319  62
       if( src == Short.TYPE || Short.class.isAssignableFrom( src ) ){
 320  4
          assignable = (isByte( dest )) ? true : assignable;
 321  
       }
 322  
 
 323  62
       return assignable;
 324  
    }
 325  
 
 326  
    private boolean isByte( Class clazz )
 327  
    {
 328  20
       return Byte.class.isAssignableFrom( clazz ) || clazz == Byte.TYPE;
 329  
    }
 330  
 
 331  
    private boolean isFloat( Class clazz )
 332  
    {
 333  4
       return Float.class.isAssignableFrom( clazz ) || clazz == Float.TYPE;
 334  
    }
 335  
 
 336  
    private boolean isInteger( Class clazz )
 337  
    {
 338  12
       return Integer.class.isAssignableFrom( clazz ) || clazz == Integer.TYPE;
 339  
    }
 340  
 
 341  
    private boolean isLong( Class clazz )
 342  
    {
 343  8
       return Long.class.isAssignableFrom( clazz ) || clazz == Long.TYPE;
 344  
    }
 345  
 
 346  
    private boolean isShort( Class clazz )
 347  
    {
 348  16
       return Short.class.isAssignableFrom( clazz ) || clazz == Short.TYPE;
 349  
    }
 350  
 }