View Javadoc

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: 800112 $ $Date: 2009-08-02 13:23:37 -0400 (Sun, 02 Aug 2009) $
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 == null) {
162             return false;
163         }
164         try {
165             TransformerMap rhs = (TransformerMap) other;
166             if (! defaultTransformer.equals(rhs.defaultTransformer)) {
167                 return false;
168             }
169             if (map.size() != rhs.map.size()) {
170                 return false;
171             }
172             for (Map.Entry<Class<?>, NumberTransformer> entry : map.entrySet()) {
173                 if (! entry.getValue().equals(rhs.map.get(entry.getKey()))) {
174                     return false;
175                 }
176             }
177             return true;
178         } catch (ClassCastException cce) {
179             return false;
180         }
181     }
182     
183     /** {@inheritDoc} */
184     @Override
185     public int hashCode() {
186         int hash = defaultTransformer.hashCode();
187         for (NumberTransformer t : map.values()) {
188             hash = hash * 31 + t.hashCode();
189         }
190         return hash;
191     }
192 
193 }