001/*
002 * This file is part of the Kompics component model runtime.
003 *
004 * Copyright (C) 2009 Swedish Institute of Computer Science (SICS) 
005 * Copyright (C) 2009 Royal Institute of Technology (KTH)
006 *
007 * This program is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU General Public License
009 * as published by the Free Software Foundation; either version 2
010 * of the License, or (at your option) any later version.
011 *
012 * This program is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015 * GNU General Public License for more details.
016 *
017 * You should have received a copy of the GNU General Public License
018 * along with this program; if not, write to the Free Software
019 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
020 */
021package se.sics.kompics.config;
022
023import com.google.common.collect.HashMultimap;
024import java.net.InetAddress;
025import java.net.UnknownHostException;
026
027/**
028 *
029 * @author Lars Kroll {@literal <[email protected]>}
030 */
031public abstract class Conversions {
032
033    private static final HashMultimap<Class<?>, Converter<?>> converters = HashMultimap.create();
034
035    static {
036        // Numbers
037        Converter<Long> longConv = new Converter<Long>() {
038
039            @Override
040            public Long convert(Object o) {
041                if (o instanceof Number) {
042                    Number n = (Number) o;
043                    return n.longValue();
044                }
045                if (o instanceof String) {
046                    return Long.parseLong((String) o);
047                }
048                return null;
049            }
050
051            @Override
052            public Class<Long> type() {
053                return Long.class;
054            }
055        };
056        converters.put(longConv.type(), longConv);
057        Converter<Integer> intConv = new Converter<Integer>() {
058
059            @Override
060            public Integer convert(Object o) {
061                if (o instanceof Number) {
062                    Number n = (Number) o;
063                    return n.intValue();
064                }
065                if (o instanceof String) {
066                    return Integer.parseInt((String) o);
067                }
068                return null;
069            }
070
071            @Override
072            public Class<Integer> type() {
073                return Integer.class;
074            }
075        };
076        converters.put(intConv.type(), intConv);
077        Converter<Byte> byteConv = new Converter<Byte>() {
078
079            @Override
080            public Byte convert(Object o) {
081                if (o instanceof Number) {
082                    Number n = (Number) o;
083                    return n.byteValue();
084                }
085                if (o instanceof String) {
086                    return Byte.parseByte((String) o);
087                }
088                return null;
089            }
090
091            @Override
092            public Class<Byte> type() {
093                return Byte.class;
094            }
095        };
096        converters.put(byteConv.type(), byteConv);
097        Converter<Short> shortConv = new Converter<Short>() {
098
099            @Override
100            public Short convert(Object o) {
101                if (o instanceof Number) {
102                    Number n = (Number) o;
103                    return n.shortValue();
104                }
105                if (o instanceof String) {
106                    return Short.parseShort((String) o);
107                }
108                return null;
109            }
110
111            @Override
112            public Class<Short> type() {
113                return Short.class;
114            }
115        };
116        converters.put(shortConv.type(), shortConv);
117        Converter<Float> floatConv = new Converter<Float>() {
118
119            @Override
120            public Float convert(Object o) {
121                if (o instanceof Number) {
122                    Number n = (Number) o;
123                    return n.floatValue();
124                }
125                if (o instanceof String) {
126                    return Float.parseFloat((String) o);
127                }
128                return null;
129            }
130
131            @Override
132            public Class<Float> type() {
133                return Float.class;
134            }
135        };
136        converters.put(floatConv.type(), floatConv);
137        Converter<Double> doubleConv = new Converter<Double>() {
138
139            @Override
140            public Double convert(Object o) {
141                if (o instanceof Number) {
142                    Number n = (Number) o;
143                    return n.doubleValue();
144                }
145                if (o instanceof String) {
146                    return Double.parseDouble((String) o);
147                }
148                return null;
149            }
150
151            @Override
152            public Class<Double> type() {
153                return Double.class;
154            }
155        };
156        converters.put(doubleConv.type(), doubleConv);
157
158        // String
159        Converter<String> strConv = new Converter<String>() {
160
161            @Override
162            public String convert(Object o) {
163                return o.toString();
164            }
165
166            @Override
167            public Class<String> type() {
168                return String.class;
169            }
170        };
171        converters.put(strConv.type(), strConv);
172
173        // Boolean
174        Converter<Boolean> boolConv = new Converter<Boolean>() {
175
176            @Override
177            public Boolean convert(Object o) {
178                if (o instanceof String) {
179                    String s = (String) o;
180                    switch (s.toLowerCase()) {
181                    case "true":
182                        return true;
183                    case "yes":
184                        return true;
185                    case "t":
186                        return true;
187                    case "y":
188                        return true;
189                    case "1":
190                        return true;
191                    case "false":
192                        return false;
193                    case "no":
194                        return false;
195                    case "f":
196                        return false;
197                    case "n":
198                        return false;
199                    case "0":
200                        return false;
201                    default:
202                        return null;
203                    }
204                }
205                if (o instanceof Number) {
206                    Number n = (Number) o;
207                    return ((n.longValue() == 0) || (n.doubleValue() == 0.0));
208                }
209                return null;
210            }
211
212            @Override
213            public Class<Boolean> type() {
214                return Boolean.class;
215            }
216        };
217        converters.put(boolConv.type(), boolConv);
218
219        // InetAddress
220        Converter<InetAddress> inetConv = new Converter<InetAddress>() {
221
222            @Override
223            public InetAddress convert(Object o) {
224                if (o instanceof String) {
225                    String s = (String) o;
226                    if (!s.isEmpty()) {
227                        try {
228                            return InetAddress.getByName(s);
229                        } catch (UnknownHostException ex) {
230                            return null;
231                        }
232                    } else {
233                        return null;
234                    }
235                }
236                if (o instanceof byte[]) {
237                    byte[] b = (byte[]) o;
238                    try {
239                        return InetAddress.getByAddress(b);
240                    } catch (UnknownHostException ex) {
241                        return null;
242                    }
243                }
244                return null;
245            }
246
247            @Override
248            public Class<InetAddress> type() {
249                return InetAddress.class;
250            }
251        };
252        converters.put(inetConv.type(), inetConv);
253    }
254
255    @SuppressWarnings("unchecked")
256    public static <T> T convert(Object o, Class<T> type) {
257        // System.out.println("Converters: \n" + converters.toString());
258        // System.out.println("Trying to convert " + o + "(" + o.getClass() + ") to " +
259        // type);
260        if (type.isInstance(o)) {
261            return type.cast(o);
262        }
263        T val = null;
264        for (Converter<?> c : converters.get(type)) {
265            // System.out.println("Trying converter " + c + " with type " + c.type());
266            Converter<T> tc = (Converter<T>) c; // must be possible because it was at type in converters
267            try {
268                val = tc.convert(o);
269            } catch (Exception ex) {
270                // do nothing, simply assume this converter didn't work
271            }
272        }
273        // System.out.println("Final value is " + val);
274        return val; // last write wins
275    }
276
277    public static void register(Converter<?> c) {
278        converters.put(c.type(), c);
279    }
280
281    public static String asString() {
282        return "Converters: \n" + converters.toString();
283    }
284}