Coverage Report - net.sf.ezmorph.MorpherRegistry
 
Classes in this File Line Coverage Branch Coverage Complexity
MorpherRegistry
95%
55/58
76%
32/42
3.556
 
 1  
 /*
 2  
  * Copyright 2006-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;
 18  
 
 19  
 import java.io.Serializable;
 20  
 import java.lang.reflect.Method;
 21  
 import java.util.ArrayList;
 22  
 import java.util.HashMap;
 23  
 import java.util.Iterator;
 24  
 import java.util.List;
 25  
 import java.util.Map;
 26  
 
 27  
 import net.sf.ezmorph.object.IdentityObjectMorpher;
 28  
 
 29  
 /**
 30  
  * Convenient class that manages Morphers.<br>
 31  
  * A MorpherRehistry manages a group of Morphers. A Morpher will always be
 32  
  * associated with a target class, it is possible to have several Morphers
 33  
  * registered for a target class, if this is the case, the first Morpher will be
 34  
  * used when performing a conversion and no specific Morpher is selected in
 35  
  * advance.<br>
 36  
  * {@link MorphUtils} may be used to register standard Morphers for primitive
 37  
  * types and primitive wrappers, as well as arrays of those types.
 38  
  *
 39  
  * @author Andres Almiray <aalmiray@users.sourceforge.net>
 40  
  */
 41  
 public class MorpherRegistry implements Serializable
 42  
 {
 43  
    private static final long serialVersionUID = -3894767123320768419L;
 44  565
    private Map morphers = new HashMap();
 45  
 
 46  142
    public MorpherRegistry()
 47  423
    {
 48  
 
 49  565
    }
 50  
 
 51  
    /**
 52  
     * Deregisters all morphers.
 53  
     */
 54  
    public synchronized void clear()
 55  
    {
 56  505
       morphers.clear();
 57  505
    }
 58  
 
 59  
    /**
 60  
     * Deregister all Morphers of a type.<br>
 61  
     *
 62  
     * @param class the target type the Morphers morph to
 63  
     */
 64  
    public synchronized void clear( Class type )
 65  
    {
 66  4
       List registered = (List) morphers.get( type );
 67  4
       if( registered != null ){
 68  4
          morphers.remove( type );
 69  
       }
 70  4
    }
 71  
 
 72  
    /**
 73  
     * Deregister the specified Morpher.<br>
 74  
     * The registry will remove the target <code>Class</code> from the morphers
 75  
     * Map if it has no other registered morphers.
 76  
     *
 77  
     * @param morpher the target Morpher to remove
 78  
     */
 79  
    public synchronized void deregisterMorpher( Morpher morpher )
 80  
    {
 81  4
       List registered = (List) morphers.get( morpher.morphsTo() );
 82  4
       if( registered != null && !registered.isEmpty() ){
 83  4
          registered.remove( morpher );
 84  4
          if( registered.isEmpty() ){
 85  4
             morphers.remove( morpher.morphsTo() );
 86  
          }
 87  
       }
 88  4
    }
 89  
 
 90  
    /**
 91  
     * Returns a morpher for <code>clazz</code>.<br>
 92  
     * If several morphers are found for that class, it returns the first. If no
 93  
     * Morpher is found it will return the IdentityObjectMorpher.
 94  
     *
 95  
     * @param clazz the target class for which a Morpher may be associated
 96  
     */
 97  
    public synchronized Morpher getMorpherFor( Class clazz )
 98  
    {
 99  2108
       List registered = (List) morphers.get( clazz );
 100  2108
       if( registered == null || registered.isEmpty() ){
 101  
          // no morpher registered for clazz
 102  200
          return IdentityObjectMorpher.getInstance();
 103  
       }else{
 104  1908
          return (Morpher) registered.get( 0 );
 105  
       }
 106  
    }
 107  
 
 108  
    /**
 109  
     * Returns all morphers for <code>clazz</code>.<br>
 110  
     * If no Morphers are found it will return an array containing the
 111  
     * IdentityObjectMorpher.
 112  
     *
 113  
     * @param clazz the target class for which a Morpher or Morphers may be
 114  
     *        associated
 115  
     */
 116  
    public synchronized Morpher[] getMorphersFor( Class clazz )
 117  
    {
 118  432
       List registered = (List) morphers.get( clazz );
 119  432
       if( registered == null || registered.isEmpty() ){
 120  
          // no morphers registered for clazz
 121  4
          return new Morpher[] { IdentityObjectMorpher.getInstance() };
 122  
       }else{
 123  428
          Morpher[] morphs = new Morpher[registered.size()];
 124  428
          int k = 0;
 125  646
          for( Iterator i = registered.iterator(); i.hasNext(); ){
 126  436
             morphs[k++] = (Morpher) i.next();
 127  
          }
 128  428
          return morphs;
 129  
       }
 130  
    }
 131  
 
 132  
    /**
 133  
     * Morphs and object to the specified target class.<br>
 134  
     * This method uses reflection to invoke primitive Morphers and Morphers that
 135  
     * do not implement ObjectMorpher.
 136  
     *
 137  
     * @param target the target class to morph to
 138  
     * @param value the value to morph
 139  
     * @return an instance of the target class if a suitable Morpher was found
 140  
     * @throws MorphException if an error occurs during the conversion
 141  
     */
 142  
    public Object morph( Class target, Object value )
 143  
    {
 144  2402
       if( value == null ){
 145  
          // give the first morpher in the list a shot to convert
 146  
          // the value as we can't access type information on it
 147  1978
          Morpher morpher = getMorpherFor( target );
 148  1978
          if( morpher instanceof ObjectMorpher ){
 149  1202
             return ((ObjectMorpher) morpher).morph( value );
 150  
          }else{
 151  
             try{
 152  969
                Method morphMethod = morpher.getClass()
 153  197
                      .getDeclaredMethod( "morph", new Class[] { Object.class } );
 154  772
                return morphMethod.invoke( morpher, new Object[] { value } );
 155  
             }
 156  4
             catch( Exception e ){
 157  4
                throw new MorphException( e );
 158  
             }
 159  
          }
 160  
       }
 161  
 
 162  424
       Morpher[] morphers = getMorphersFor( target );
 163  428
       for( int i = 0; i < morphers.length; i++ ){
 164  428
          Morpher morpher = morphers[i];
 165  428
          if( morpher.supports( value.getClass() ) ){
 166  424
             if( morpher instanceof ObjectMorpher ){
 167  386
                return ((ObjectMorpher) morpher).morph( value );
 168  
             }else{
 169  
                try{
 170  48
                   Method morphMethod = morpher.getClass()
 171  10
                         .getDeclaredMethod( "morph", new Class[] { Object.class } );
 172  38
                   return morphMethod.invoke( morpher, new Object[] { value } );
 173  
                }
 174  0
                catch( Exception e ){
 175  0
                   throw new MorphException( e );
 176  
                }
 177  
             }
 178  
          }
 179  
       }
 180  0
       return value;
 181  
    }
 182  
 
 183  
    /**
 184  
     * Register a Morpher for a target <code>Class</code>.<br>
 185  
     * The target class is the class this Morpher morphs to. If there are another
 186  
     * morphers registered to that class, it will be appended to a List.
 187  
     *
 188  
     * @param morpher a Morpher to register. The method <code>morphsTo()</code>
 189  
     *        is used to associate the Morpher to a target Class
 190  
     */
 191  
    public void registerMorpher( Morpher morpher )
 192  
    {
 193  20736
       registerMorpher( morpher, false );
 194  20736
    }
 195  
 
 196  
    /**
 197  
     * Register a Morpher for a target <code>Class</code>.<br>
 198  
     * The target class is the class this Morpher morphs to. If there are another
 199  
     * morphers registered to that class, it will be appended to a List.
 200  
     *
 201  
     * @param morpher a Morpher to register. The method <code>morphsTo()</code>
 202  
     *        is used to associate the Morpher to a target Class
 203  
     * @param override if registering teh Morpher should override all previously
 204  
     *        registered morphers for the target type
 205  
     */
 206  
    public synchronized void registerMorpher( Morpher morpher, boolean override )
 207  
    {
 208  20736
       List registered = (List) morphers.get( morpher.morphsTo() );
 209  20736
       if( override || registered == null ){
 210  20728
          registered = new ArrayList();
 211  20728
          morphers.put( morpher.morphsTo(), registered );
 212  
       }
 213  20736
       if( !registered.contains( morpher ) ){
 214  20736
          registered.add( morpher );
 215  
       }
 216  20736
    }
 217  
 }