001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.math.util;
018
019 import java.io.Serializable;
020 import java.util.Collection;
021 import java.util.HashMap;
022 import java.util.Map;
023 import java.util.Set;
024
025 import org.apache.commons.math.MathException;
026
027 /**
028 * This TansformerMap automates the transformation of mixed object types.
029 * It provides a means to set NumberTransformers that will be selected
030 * based on the Class of the object handed to the Maps
031 * <code>double transform(Object o)</code> method.
032 * @version $Revision: 922713 $ $Date: 2010-03-14 02:26:13 +0100 (dim. 14 mars 2010) $
033 */
034 public class TransformerMap implements NumberTransformer, Serializable {
035
036 /** Serializable version identifier */
037 private static final long serialVersionUID = 4605318041528645258L;
038
039 /**
040 * A default Number Transformer for Numbers and numeric Strings.
041 */
042 private NumberTransformer defaultTransformer = null;
043
044 /**
045 * The internal Map.
046 */
047 private Map<Class<?>, NumberTransformer> map = null;
048
049 /**
050 * Build a map containing only the default transformer.
051 */
052 public TransformerMap() {
053 map = new HashMap<Class<?>, NumberTransformer>();
054 defaultTransformer = new DefaultTransformer();
055 }
056
057 /**
058 * Tests if a Class is present in the TransformerMap.
059 * @param key Class to check
060 * @return true|false
061 */
062 public boolean containsClass(Class<?> key) {
063 return map.containsKey(key);
064 }
065
066 /**
067 * Tests if a NumberTransformer is present in the TransformerMap.
068 * @param value NumberTransformer to check
069 * @return true|false
070 */
071 public boolean containsTransformer(NumberTransformer value) {
072 return map.containsValue(value);
073 }
074
075 /**
076 * Returns the Transformer that is mapped to a class
077 * if mapping is not present, this returns null.
078 * @param key The Class of the object
079 * @return the mapped NumberTransformer or null.
080 */
081 public NumberTransformer getTransformer(Class<?> key) {
082 return map.get(key);
083 }
084
085 /**
086 * Sets a Class to Transformer Mapping in the Map. If
087 * the Class is already present, this overwrites that
088 * mapping.
089 * @param key The Class
090 * @param transformer The NumberTransformer
091 * @return the replaced transformer if one is present
092 */
093 public NumberTransformer putTransformer(Class<?> key, NumberTransformer transformer) {
094 return map.put(key, transformer);
095 }
096
097 /**
098 * Removes a Class to Transformer Mapping in the Map.
099 * @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 }