Home | History | Annotate | Download | only in util
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 package org.apache.commons.math.util;
     18 
     19 import java.io.Serializable;
     20 import java.util.Collection;
     21 import java.util.HashMap;
     22 import java.util.Map;
     23 import java.util.Set;
     24 
     25 import org.apache.commons.math.MathException;
     26 
     27 /**
     28  * This TansformerMap automates the transformation of mixed object types.
     29  * It provides a means to set NumberTransformers that will be selected
     30  * based on the Class of the object handed to the Maps
     31  * <code>double transform(Object o)</code> method.
     32  * @version $Revision: 922713 $ $Date: 2010-03-14 02:26:13 +0100 (dim. 14 mars 2010) $
     33  */
     34 public class TransformerMap implements NumberTransformer, Serializable {
     35 
     36     /** Serializable version identifier */
     37     private static final long serialVersionUID = 4605318041528645258L;
     38 
     39     /**
     40      * A default Number Transformer for Numbers and numeric Strings.
     41      */
     42     private NumberTransformer defaultTransformer = null;
     43 
     44     /**
     45      * The internal Map.
     46      */
     47     private Map<Class<?>, NumberTransformer> map = null;
     48 
     49     /**
     50      * Build a map containing only the default transformer.
     51      */
     52     public TransformerMap() {
     53         map = new HashMap<Class<?>, NumberTransformer>();
     54         defaultTransformer = new DefaultTransformer();
     55     }
     56 
     57     /**
     58      * Tests if a Class is present in the TransformerMap.
     59      * @param key Class to check
     60      * @return true|false
     61      */
     62     public boolean containsClass(Class<?> key) {
     63         return map.containsKey(key);
     64     }
     65 
     66     /**
     67      * Tests if a NumberTransformer is present in the TransformerMap.
     68      * @param value NumberTransformer to check
     69      * @return true|false
     70      */
     71     public boolean containsTransformer(NumberTransformer value) {
     72         return map.containsValue(value);
     73     }
     74 
     75     /**
     76      * Returns the Transformer that is mapped to a class
     77      * if mapping is not present, this returns null.
     78      * @param key The Class of the object
     79      * @return the mapped NumberTransformer or null.
     80      */
     81     public NumberTransformer getTransformer(Class<?> key) {
     82         return map.get(key);
     83     }
     84 
     85     /**
     86      * Sets a Class to Transformer Mapping in the Map. If
     87      * the Class is already present, this overwrites that
     88      * mapping.
     89      * @param key The Class
     90      * @param transformer The NumberTransformer
     91      * @return the replaced transformer if one is present
     92      */
     93     public NumberTransformer putTransformer(Class<?> key, NumberTransformer transformer) {
     94         return map.put(key, transformer);
     95     }
     96 
     97     /**
     98      * Removes a Class to Transformer Mapping in the Map.
     99      * @param key The Class
    100      * @return the removed transformer if one is present or
    101      * null if none was present.
    102      */
    103     public NumberTransformer removeTransformer(Class<?> key) {
    104         return map.remove(key);
    105     }
    106 
    107     /**
    108      * Clears all the Class to Transformer mappings.
    109      */
    110     public void clear() {
    111         map.clear();
    112     }
    113 
    114     /**
    115      * Returns the Set of Classes used as keys in the map.
    116      * @return Set of Classes
    117      */
    118     public Set<Class<?>> classes() {
    119         return map.keySet();
    120     }
    121 
    122     /**
    123      * Returns the Set of NumberTransformers used as values
    124      * in the map.
    125      * @return Set of NumberTransformers
    126      */
    127     public Collection<NumberTransformer> transformers() {
    128         return map.values();
    129     }
    130 
    131     /**
    132      * Attempts to transform the Object against the map of
    133      * NumberTransformers. Otherwise it returns Double.NaN.
    134      *
    135      * @param o the Object to be transformed.
    136      * @return the double value of the Object.
    137      * @throws MathException if the Object can not be transformed into a Double.
    138      * @see org.apache.commons.math.util.NumberTransformer#transform(java.lang.Object)
    139      */
    140     public double transform(Object o) throws MathException {
    141         double value = Double.NaN;
    142 
    143         if (o instanceof Number || o instanceof String) {
    144             value = defaultTransformer.transform(o);
    145         } else {
    146             NumberTransformer trans = getTransformer(o.getClass());
    147             if (trans != null) {
    148                 value = trans.transform(o);
    149             }
    150         }
    151 
    152         return value;
    153     }
    154 
    155     /** {@inheritDoc} */
    156     @Override
    157     public boolean equals(Object other) {
    158         if (this == other) {
    159             return true;
    160         }
    161         if (other instanceof TransformerMap) {
    162             TransformerMap rhs = (TransformerMap) other;
    163             if (! defaultTransformer.equals(rhs.defaultTransformer)) {
    164                 return false;
    165             }
    166             if (map.size() != rhs.map.size()) {
    167                 return false;
    168             }
    169             for (Map.Entry<Class<?>, NumberTransformer> entry : map.entrySet()) {
    170                 if (! entry.getValue().equals(rhs.map.get(entry.getKey()))) {
    171                     return false;
    172                 }
    173             }
    174             return true;
    175         }
    176         return false;
    177     }
    178 
    179     /** {@inheritDoc} */
    180     @Override
    181     public int hashCode() {
    182         int hash = defaultTransformer.hashCode();
    183         for (NumberTransformer t : map.values()) {
    184             hash = hash * 31 + t.hashCode();
    185         }
    186         return hash;
    187     }
    188 
    189 }
    190