001/*
002@license.text@
003 */
004package com.hammurapi.convert;
005
006import java.io.ByteArrayInputStream;
007import java.io.ByteArrayOutputStream;
008import java.io.File;
009import java.io.FileInputStream;
010import java.io.FileOutputStream;
011import java.io.FileReader;
012import java.io.FileWriter;
013import java.io.IOException;
014import java.io.InputStream;
015import java.io.InputStreamReader;
016import java.io.Reader;
017import java.io.StringReader;
018import java.io.StringWriter;
019import java.lang.reflect.Constructor;
020import java.math.BigDecimal;
021import java.net.URL;
022import java.util.ArrayList;
023import java.util.Collection;
024import java.util.Collections;
025import java.util.List;
026
027import com.hammurapi.common.Context;
028
029/**
030 * @author Pavel Vlasov
031 * @version $Revision: 1.7 $
032 */
033public class FoundationAtomicConvertersBundle implements AtomicConvertersBundle {
034
035        private List<AtomicConverter<? extends Object,? extends Object>> converters=new ArrayList<AtomicConverter<? extends Object,? extends Object>>();
036        
037        public Collection<AtomicConverter<? extends Object,? extends Object>> getConverters() {
038                return Collections.unmodifiableCollection(converters);
039        }
040
041    /**
042     * Creates new composite converter populated by default with some generic converters.
043     */
044        @SuppressWarnings("unchecked")
045        public FoundationAtomicConvertersBundle() {
046                addConverter(Number.class, byte.class, "byteValue", null);
047                addConverter(Number.class, double.class, "doubleValue", null);
048                addConverter(Number.class, float.class, "floatValue", null);
049                addConverter(Number.class, int.class, "intValue", null);
050                addConverter(Number.class, long.class, "longValue", null);
051                addConverter(Number.class, short.class, "shortValue", null);
052                
053                addConverter(Number.class, Byte.class, "byteValue", null);
054                addConverter(Number.class, Double.class, "doubleValue", null);
055                addConverter(Number.class, Float.class, "floatValue", null);
056                addConverter(Number.class, Integer.class, "intValue", null);
057                addConverter(Number.class, Long.class, "longValue", null);
058                addConverter(Number.class, Short.class, "shortValue", null);
059                
060                addConverter(Object.class, String.class, "toString", null);
061                
062                
063                addConverter(Boolean.class, boolean.class, "booleanValue", null);
064                
065                converters.addAll(ReflectionConverter.discoverConstructorConverters(String.class));
066                converters.addAll(ReflectionConverter.discoverConstructorConverters(Integer.class));
067                converters.addAll(ReflectionConverter.discoverConstructorConverters(Long.class));
068                converters.addAll(ReflectionConverter.discoverConstructorConverters(Double.class));
069                converters.addAll(ReflectionConverter.discoverConstructorConverters(Float.class));
070                converters.addAll(ReflectionConverter.discoverConstructorConverters(Byte.class));
071                converters.addAll(ReflectionConverter.discoverConstructorConverters(Short.class));
072                converters.addAll(ReflectionConverter.discoverConstructorConverters(BigDecimal.class));
073                
074                try {
075                        addConverter(File.class, FileReader.class, null, FileReader.class.getConstructor(File.class));
076                        addConverter(File.class, FileInputStream.class, null, FileInputStream.class.getConstructor(File.class));
077                        
078                        addConverter(File.class, FileOutputStream.class, null, FileOutputStream.class.getConstructor(File.class));
079                        addConverter(File.class, FileWriter.class, null, FileWriter.class.getConstructor(File.class));
080                        
081                        addConverter(InputStream.class, InputStreamReader.class, null, InputStreamReader.class.getConstructor(InputStream.class));
082                        addConverter(URL.class, InputStream.class, "openStream", null);
083                } catch (SecurityException e) {
084                        throw new ConversionException(e);
085                } catch (NoSuchMethodException e) {
086                        throw new ConversionException(e);
087                }
088                
089                converters.add(new AtomicConverterBase(String.class, boolean.class) {
090
091                        public Object convert(Object source, Converter master, Context context, ClassLoader classLoader) {
092                                if (source==null) {
093                                        return Boolean.FALSE;
094                                }
095                                
096                                String str = ((String) source).trim();
097                                if (str.length()==0 || "no".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str) || "0".equals(source) || "".equals(source)) {
098                                        return Boolean.FALSE;
099                                } else if ("yes".equalsIgnoreCase(str) || "true".equalsIgnoreCase(str) || "1".equals(source) || "on".equals(source)) {
100                                        return Boolean.TRUE;
101                                } 
102                                
103                                return null;
104                        }
105                        
106                });
107                
108                converters.add(new AtomicConverterBase<String,Class>(String.class, Class.class) {
109
110                        public Class convert(String source, Converter master, Context context, ClassLoader classLoader) {
111                                if (source==null) {
112                                        return null;
113                                }
114                                
115                                try {
116                                        return classLoader.loadClass(source.trim());
117                                } catch (ClassNotFoundException e) {
118                                        throw new ConversionException(e);
119                                }
120                        }
121                        
122                });
123                
124                converters.add(new AtomicConverterBase<ByteArrayOutputStream,byte[]>(ByteArrayOutputStream.class, byte[].class) {
125
126                        @Override
127                        public byte[] convert(ByteArrayOutputStream source,     Converter master, Context context, ClassLoader classLoader) {
128                                if (source==null) {
129                                        return null;
130                                }
131                                
132                                try {
133                                        source.close();
134                                } catch (IOException e) {
135                                        throw new ConversionException(e);
136                                }
137                                
138                                return source.toByteArray();
139                        }
140                        
141                });
142                
143                converters.add(new AtomicConverterBase<ByteArrayOutputStream,InputStream>(ByteArrayOutputStream.class, InputStream.class) {
144
145                        @Override
146                        public InputStream convert(ByteArrayOutputStream source,        Converter master, Context context, ClassLoader classLoader) {
147                                if (source==null) {
148                                        return null;
149                                }
150                                
151                                try {
152                                        source.close();
153                                } catch (IOException e) {
154                                        throw new ConversionException(e);
155                                }
156                                
157                                return new ByteArrayInputStream(source.toByteArray());
158                        }
159                        
160                });
161                
162                converters.add(new AtomicConverterBase<StringWriter,String>(StringWriter.class, String.class) {
163
164                        @Override
165                        public String convert(StringWriter source,      Converter master, Context context, ClassLoader classLoader) {
166                                if (source==null) {
167                                        return null;
168                                }
169                                
170                                try {
171                                        source.close();
172                                } catch (IOException e) {
173                                        throw new ConversionException(e);
174                                }
175                                
176                                return source.toString();
177                        }
178                        
179                });
180                
181                converters.add(new AtomicConverterBase<StringWriter, Reader>(StringWriter.class, Reader.class) {
182
183                        @Override
184                        public Reader convert(StringWriter source, Converter master, Context context, ClassLoader classLoader) {
185                                if (source==null) {
186                                        return null;
187                                }
188                                
189                                try {
190                                        source.close();
191                                } catch (IOException e) {
192                                        throw new ConversionException(e);
193                                }
194                                
195                                return new StringReader(source.toString());
196                        }
197                        
198                });
199                
200                converters.add(new AtomicConverterBase(String.class, byte.class) {
201
202                        public Object convert(Object source, Converter master, Context context, ClassLoader classLoader) {
203                                return new Byte((String) source);
204                        }
205                        
206                });
207                
208                converters.add(new AtomicConverterBase(String.class, double.class) {
209
210                        public Object convert(Object source, Converter master, Context context, ClassLoader classLoader) {
211                                return new Double((String) source);
212                        }
213                        
214                });
215                
216                converters.add(new AtomicConverterBase(String.class, float.class) {
217
218                        public Object convert(Object source, Converter master, Context context, ClassLoader classLoader) {
219                                return new Float((String) source);
220                        }
221                        
222                });
223                
224
225                converters.add(new AtomicConverterBase(String.class, int.class) {
226
227                        public Object convert(Object source, Converter master, Context context, ClassLoader classLoader) {
228                                return new Integer((String) source);
229                        }
230                        
231                });
232                
233
234                converters.add(new AtomicConverterBase(String.class, long.class) {
235
236                        public Object convert(Object source, Converter master, Context context, ClassLoader classLoader) {
237                                return new Long((String) source);
238                        }
239                        
240                });
241                
242
243                converters.add(new AtomicConverterBase(String.class, short.class) {
244
245                        public Object convert(Object source, Converter master, Context context, ClassLoader classLoader) {
246                                return new Short((String) source);
247                        }
248                        
249                });
250                                
251                converters.add(new AtomicConverterBase(String.class, Class.class) {
252
253                        public Object convert(Object source, Converter master, Context context, ClassLoader classLoader) {
254                                try {
255                                        return Class.forName((String) source);
256                                } catch (ClassNotFoundException e) {
257                                        throw new ConversionException(e);
258                                }
259                        }
260                        
261                });             
262                
263    }
264                
265        private <S, T> void  addConverter(Class<S> source, Class<T> target, String accessor, Constructor<? extends T> constructor) {
266                try {
267                        converters.add(new ReflectionConverter<S, T>(accessor==null ? null : source.getMethod(accessor), constructor));
268                } catch (Exception e) {
269                        throw new ConversionException(e);
270                }
271        }
272                
273}