Coverage Report - net.sf.ezmorph.bean.MorphDynaClass
 
Classes in this File Line Coverage Branch Coverage Complexity
MorphDynaClass
93%
100/107
93%
50/54
3.267
MorphDynaClass$1
88%
7/8
50%
2/4
3.267
 
 1  3
 /*
 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.util.Arrays;
 21  
 import java.util.Comparator;
 22  
 import java.util.HashMap;
 23  
 import java.util.Iterator;
 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  
 
 37  
 /**
 38  
  * @author Andres Almiray <aalmiray@users.sourceforge.net>
 39  
  */
 40  3
 public final class MorphDynaClass implements DynaClass, Serializable
 41  
 {
 42  4
    private static final Comparator dynaPropertyComparator = new Comparator(){
 43  
       public int compare( Object a, Object b )
 44  
       {
 45  5003
          if( a instanceof DynaProperty && b instanceof DynaProperty ){
 46  5003
             DynaProperty p1 = (DynaProperty) a;
 47  5003
             DynaProperty p2 = (DynaProperty) b;
 48  8756
             return p1.getName()
 49  3753
                   .compareTo( p2.getName() );
 50  
          }
 51  0
          return -1;
 52  
       }
 53  
    };
 54  
 
 55  
    private static final long serialVersionUID = -613214016860871560L;
 56  
 
 57  
    private Map attributes;
 58  
    private Class beanClass;
 59  
    private DynaProperty dynaProperties[];
 60  
    private String name;
 61  267
    private Map properties = new HashMap();
 62  
    private Class type;
 63  
 
 64  
    public MorphDynaClass( Map attributes )
 65  
    {
 66  255
       this( null, null, attributes );
 67  239
    }
 68  
 
 69  
    public MorphDynaClass( Map attributes, boolean exceptionOnEmptyAttributes )
 70  
    {
 71  8
       this( null, null, attributes, exceptionOnEmptyAttributes );
 72  0
    }
 73  
 
 74  
    public MorphDynaClass( String name, Class type, Map attributes )
 75  
    {
 76  259
       this( name, type, attributes, false );
 77  239
    }
 78  
 
 79  201
    public MorphDynaClass( String name, Class type, Map attributes,
 80  
          boolean exceptionOnEmptyAttributes )
 81  66
    {
 82  267
       if( name == null ){
 83  263
          name = "MorphDynaClass";
 84  
       }
 85  267
       if( type == null ){
 86  264
          type = MorphDynaBean.class;
 87  
       }
 88  267
       if( !MorphDynaBean.class.isAssignableFrom( type ) ){
 89  4
          throw new MorphException( "MorphDynaBean is not assignable from " + type.getName() );
 90  
       }
 91  263
       if( attributes == null || attributes.isEmpty() ){
 92  16
          if( exceptionOnEmptyAttributes ){
 93  8
             throw new MorphException( "Attributes map is null or empty." );
 94  
          }else{
 95  8
             attributes = new HashMap();
 96  
          }
 97  
       }
 98  255
       this.name = name;
 99  255
       this.type = type;
 100  255
       this.attributes = attributes;
 101  255
       process();
 102  239
    }
 103  
 
 104  
    public boolean equals( Object obj )
 105  
    {
 106  24
       if( this == obj ){
 107  4
          return true;
 108  
       }
 109  
 
 110  20
       if( obj == null ){
 111  4
          return false;
 112  
       }
 113  
 
 114  16
       if( !(obj instanceof MorphDynaClass) ){
 115  4
          return false;
 116  
       }
 117  
 
 118  12
       MorphDynaClass other = (MorphDynaClass) obj;
 119  21
       EqualsBuilder builder = new EqualsBuilder().append( this.name, other.name )
 120  9
             .append( this.type, other.type );
 121  12
       if( dynaProperties.length != other.dynaProperties.length ){
 122  4
          return false;
 123  
       }
 124  16
       for( int i = 0; i < dynaProperties.length; i++ ){
 125  8
          DynaProperty a = this.dynaProperties[i];
 126  8
          DynaProperty b = other.dynaProperties[i];
 127  8
          builder.append( a.getName(), b.getName() );
 128  8
          builder.append( a.getType(), b.getType() );
 129  
       }
 130  8
       return builder.isEquals();
 131  
    }
 132  
 
 133  
    public DynaProperty[] getDynaProperties()
 134  
    {
 135  28
       return dynaProperties;
 136  
    }
 137  
 
 138  
    public DynaProperty getDynaProperty( String propertyName )
 139  
    {
 140  2175
       if( propertyName == null ){
 141  4
          throw new MorphException( "Unnespecified bean property name" );
 142  
 
 143  
       }
 144  2171
       return (DynaProperty) properties.get( propertyName );
 145  
    }
 146  
 
 147  
    public String getName()
 148  
    {
 149  0
       return this.name;
 150  
    }
 151  
 
 152  
    public int hashCode()
 153  
    {
 154  70
       HashCodeBuilder builder = new HashCodeBuilder().append( name )
 155  30
             .append( type );
 156  252
       for( int i = 0; i < dynaProperties.length; i++ ){
 157  212
          builder.append( this.dynaProperties[i].getName() );
 158  212
          builder.append( this.dynaProperties[i].getType() );
 159  
       }
 160  40
       return builder.toHashCode();
 161  
    }
 162  
 
 163  
    public DynaBean newInstance() throws IllegalAccessException, InstantiationException
 164  
    {
 165  187
       return newInstance( null );
 166  
    }
 167  
 
 168  
    public DynaBean newInstance( MorpherRegistry morpherRegistry ) throws IllegalAccessException,
 169  
          InstantiationException
 170  
    {
 171  199
       if( morpherRegistry == null ){
 172  187
          morpherRegistry = new MorpherRegistry();
 173  187
          MorphUtils.registerStandardMorphers( morpherRegistry );
 174  
       }
 175  199
       MorphDynaBean dynaBean = (MorphDynaBean) getBeanClass().newInstance();
 176  199
       dynaBean.setDynaBeanClass( this );
 177  199
       dynaBean.setMorpherRegistry( morpherRegistry );
 178  349
       Iterator keys = attributes.keySet()
 179  150
             .iterator();
 180  2179
       while( keys.hasNext() ){
 181  1830
          String key = (String) keys.next();
 182  1830
          dynaBean.set( key, null );
 183  456
       }
 184  199
       return dynaBean;
 185  
    }
 186  
 
 187  
    public String toString()
 188  
    {
 189  0
       return new ToStringBuilder( this ).append( "name", this.name )
 190  0
             .append( "type", this.type )
 191  0
             .append( "attributes", this.attributes )
 192  0
             .toString();
 193  
    }
 194  
 
 195  
    protected Class getBeanClass()
 196  
    {
 197  199
       if( this.beanClass == null ){
 198  0
          process();
 199  
       }
 200  199
       return this.beanClass;
 201  
    }
 202  
 
 203  
    private void process()
 204  
    {
 205  255
       this.beanClass = this.type;
 206  
 
 207  
       try{
 208  447
          Iterator entries = attributes.entrySet()
 209  192
                .iterator();
 210  255
          dynaProperties = new DynaProperty[attributes.size()];
 211  255
          int i = 0;
 212  2357
          while( entries.hasNext() ){
 213  1926
             Map.Entry entry = (Map.Entry) entries.next();
 214  1926
             String pname = (String) entry.getKey();
 215  1926
             Object pclass = entry.getValue();
 216  1926
             DynaProperty dynaProperty = null;
 217  1926
             if( pclass instanceof String ){
 218  12
                Class klass = (Class) Class.forName( (String) pclass );
 219  8
                if( klass.isArray() && klass.getComponentType()
 220  3
                      .isArray() ){
 221  4
                   throw new MorphException( "Multidimensional arrays are not supported" );
 222  
                }
 223  4
                dynaProperty = new DynaProperty( pname, klass );
 224  1438
             }else if( pclass instanceof Class ){
 225  1910
                Class klass = (Class) pclass;
 226  1910
                if( klass.isArray() && klass.getComponentType()
 227  72
                      .isArray() ){
 228  4
                   throw new MorphException( "Multidimensional arrays are not supported" );
 229  
                }
 230  1906
                dynaProperty = new DynaProperty( pname, klass );
 231  475
             }else{
 232  4
                throw new MorphException( "Type must be String or Class" );
 233  
             }
 234  1910
             properties.put( dynaProperty.getName(), dynaProperty );
 235  1910
             dynaProperties[i++] = dynaProperty;
 236  476
          }
 237  
       }
 238  4
       catch( ClassNotFoundException cnfe ){
 239  4
          throw new MorphException( cnfe );
 240  59
       }
 241  
 
 242  
       // keep properties sorted by name
 243  239
       Arrays.sort( dynaProperties, 0, dynaProperties.length, dynaPropertyComparator );
 244  239
    }
 245  
 }