Coverage Report - org.apache.commons.convert1.ConvertRegistry
 
Classes in this File Line Coverage Branch Coverage Complexity
ConvertRegistry
0%
0/43
0%
0/20
2.5
 
 1  
 /*
 2  
  *  Copyright 2003-2004 The Apache Software Foundation
 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  
 package org.apache.commons.convert1;
 17  
 
 18  
 
 19  
 import java.util.Iterator;
 20  
 import java.util.Map;
 21  
 
 22  
 import org.apache.commons.convert1.util.ClassMap;
 23  
 import org.apache.commons.convert1.util.Inheritor;
 24  
 
 25  
 /**
 26  
  * Stores Converters under a dual-key system of fromClass to toClass.
 27  
  * 
 28  
  * @author Henri Yandell
 29  
  * @version $Id: ConvertRegistry.java 155441 2005-02-26 13:19:22Z dirkv $
 30  
  * @since 0.1
 31  
  */
 32  
 
 33  
 public class ConvertRegistry {
 34  
 
 35  
     // ------------------------------------------------------- Class Methods
 36  
 
 37  
     // ------------------------------------------------------- Variables
 38  
 
 39  
 
 40  
     /**
 41  
      * A ClassMap of Class to ClassMap. This then contains 
 42  
      * a Class to {@link Converter} mapping.
 43  
      */
 44  0
     private ClassMap converters = new ClassMap();
 45  
 
 46  
     // ------------------------------------------------------- Constructors
 47  
 
 48  
     // TODO: Allow the Inheritor's used by the ClassMap to be set by 
 49  
     //       the user so that different ways of looking up may be used
 50  0
     public ConvertRegistry() {
 51  0
     }
 52  
 
 53  
     // --------------------------------------------------------- Public Methods
 54  
     
 55  
     // ------------------------------------------------------ Static Properties
 56  
 
 57  
 
 58  
     /**
 59  
      * Convert the specified value into a String.  If the specified value
 60  
      * is an array, the first element (converted to a String) will be
 61  
      * returned.  The registered {@link Converter} for the
 62  
      * <code>java.lang.String</code> class will be used, which allows
 63  
      * applications to customize Object->String conversions (the default
 64  
      * implementation simply uses toString()).
 65  
      *
 66  
      * @param value Value to be converted (may be null)
 67  
      */
 68  
     /*
 69  
     // This whole method appears to be a waste of time. 
 70  
     // It's a way to plugin a StringConverter, but why treat Strings 
 71  
     // in a special way?
 72  
     public String convert(Object value) {
 73  
 
 74  
         if (value == null) {
 75  
             return ((String) null);
 76  
         } else if (value.getClass().isArray()) {
 77  
 
 78  
             //H? This seems bad. String[0] becomes null.
 79  
             //   Why not return String[]??
 80  
             if (Array.getLength(value) < 1) {
 81  
                 return (null);
 82  
             }
 83  
             value = Array.get(value, 0);
 84  
             if (value == null) {
 85  
                 return ((String) null);
 86  
             } else {
 87  
                 Converter converter = lookup(String.class);
 88  
                 return ((String) converter.convert(String.class, value));
 89  
             }
 90  
         } else {
 91  
             Converter converter = lookup(String.class);
 92  
             return ((String) converter.convert(String.class, value));
 93  
         }
 94  
 
 95  
     }
 96  
     */
 97  
 
 98  
 
 99  
     /**
 100  
      * Convert the specified value to an object of the specified class (if
 101  
      * possible).  Otherwise, return a String representation of the value.
 102  
      *
 103  
      * @param value Value to be converted (may be null)
 104  
      * @param clazz Java class to be converted to
 105  
      *
 106  
      * @exception ConversionException if thrown by an underlying Converter
 107  
      */
 108  
     public Object convert(Object value, Class toClass) {
 109  
         //H? If value == null, return null??
 110  0
         if(value == null) {
 111  0
             return null;
 112  
         }
 113  
 
 114  0
         Class fromClass = value.getClass();
 115  
 
 116  0
         Converter converter = lookup(value.getClass(), toClass);
 117  
 
 118  0
         if (converter == null) {
 119  
             //H? If value.getClass() == toClass, do we auto-return?
 120  0
             if(value.getClass() == toClass) {
 121  0
                 return value;
 122  
             }
 123  
 
 124  0
             Inheritor inh = converters.getInheritor();
 125  
 
 126  0
             Iterator itr = inh.iterator();
 127  
 
 128  0
             while( itr.hasNext() && converter == null ) {
 129  0
                 converter = lookup( value.getClass(), toClass );
 130  
             }
 131  
 
 132  
             //H? Try to treat converter as a Collection concept
 133  
             //   Or should this be a converter of its own? 
 134  
             //   How would it be mapped? To every possible 
 135  
             //   collective type? primitve[], Object[], Collection, 
 136  
             //   Map?
 137  
             //   Yes, this should be a converter.
 138  
 
 139  
             //H? Throw exception?  return null? Treat as String? 
 140  
             //H? How about returning value? Should this be a user choice?
 141  0
             if( converter == null ) {
 142  0
                 converter = new IdentityConverter();
 143  
             }
 144  
         }
 145  
 
 146  
         //H? Should this check if the returned value is 
 147  
         //   the correct class?
 148  0
         return converter.convert(toClass, value);
 149  
 
 150  
     }
 151  
 
 152  
 
 153  
     /**
 154  
      * Convert an array of specified values to an array of objects of the
 155  
      * specified class (if possible).  If the specified Java class is itself
 156  
      * an array class, this class will be the type of the returned value.
 157  
      * Otherwise, an array will be constructed whose component type is the
 158  
      * specified class.
 159  
      *
 160  
      * @param value Value to be converted (may be null)
 161  
      * @param clazz Java array or element class to be converted to
 162  
      *
 163  
      * @exception ConversionException if thrown by an underlying Converter
 164  
      */
 165  
      //H? This method is too specific. It needs to become convertCollective
 166  
      /*
 167  
     public Object convert(String values[], Class clazz) {
 168  
 
 169  
         Class type = clazz;
 170  
         if (clazz.isArray()) {
 171  
             type = clazz.getComponentType();
 172  
         }
 173  
         Converter converter = lookup(type);
 174  
         if (converter == null) {
 175  
             converter = lookup(String.class);
 176  
         }
 177  
         Object array = Array.newInstance(type, values.length);
 178  
         for (int i = 0; i < values.length; i++) {
 179  
             Array.set(array, i, converter.convert(type, values[i]));
 180  
         }
 181  
         return (array);
 182  
 
 183  
     }
 184  
     */
 185  
 
 186  
 
 187  
     /**
 188  
      * Remove all registered {@link Converter}s.
 189  
      */
 190  
     public void clear() {
 191  
 
 192  0
                 converters.clear();
 193  
 
 194  0
     }
 195  
 
 196  
     /**
 197  
      * Remove any registered {@link Converter} for the specified destination
 198  
      * <code>Class</code>.
 199  
      *
 200  
      * @param clazz Class for which to remove a registered Converter
 201  
      */
 202  
     public void deregister(Class fromClass, Class toClass) {
 203  
 
 204  0
         Map map = (Map) converters.get(fromClass);
 205  0
         map.remove(toClass);
 206  
 
 207  0
     }
 208  
     public void fromClassDeregister(Class fromClass) {
 209  
 
 210  0
         converters.remove(fromClass);
 211  
 
 212  0
     }
 213  
     public void toClassDeregister(Class toClass) {
 214  
 
 215  
         // loop over every fromClass and remove
 216  
         // a dual indexed map will improve speed
 217  0
         Iterator itr = converters.keySet().iterator();
 218  0
         while( itr.hasNext() ) {
 219  0
             Map map = (Map) itr.next();
 220  0
             map.remove(toClass);
 221  0
         }
 222  0
     }
 223  
 
 224  
     /**
 225  
      * Look up and return any registered {@link Converter} for the specified
 226  
      * destination class; if there is no registered Converter, return
 227  
      * <code>null</code>.
 228  
      *
 229  
      * @param clazz Class for which to return a registered Converter
 230  
      */
 231  
     //H? Should this return an IdentityConverter?
 232  
     public Converter lookup(Class fromClass, Class toClass) {
 233  
 
 234  0
         Map map = (Map) converters.get(fromClass);
 235  
 
 236  0
         if(map == null) {
 237  0
             return null;
 238  
         }
 239  
 
 240  0
         Object obj = map.get(toClass);
 241  
 
 242  0
         while( obj instanceof ConverterFactory ) {
 243  0
             obj = ( (ConverterFactory) obj).create( fromClass, toClass );
 244  
         }
 245  
 
 246  
         //H? check obj is a Converter, or is ClassNotFound good enough?
 247  
 
 248  0
         return (Converter) obj;
 249  
 
 250  
     }
 251  
 
 252  
     //H? What to do here? Return a registry with a default fromClass?
 253  
     //H? rename: lookupFromClassRegistry
 254  
     //H? add: lookupToClassRegistry
 255  
 
 256  
 
 257  
     /**
 258  
      * Register a custom {@link Converter} for the specified destination
 259  
      * <code>Class</code>, replacing any previously registered Converter.
 260  
      *
 261  
      * @param converter Converter to be registered
 262  
      * @param clazz Destination class for conversions performed by this
 263  
      *  Converter
 264  
      */
 265  
     public void register(Converter converter, Class fromClass, Class toClass) {
 266  
 
 267  0
         Map map = (Map) converters.get(fromClass);
 268  
 
 269  0
         if( map == null) {
 270  0
             map = new ClassMap();
 271  0
             converters.put( fromClass, map );
 272  
         }
 273  
 
 274  0
         map.put(toClass, converter);
 275  
 
 276  0
     }
 277  
 
 278  
     //H? refactor: registerForFromClass(ConverterRegistry, Class fromClass)
 279  
     //H? refactor: registerForToClass(ConverterRegistry, Class toClass)
 280  
 }