001    /*******************************************************************************
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     * http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     *******************************************************************************/
019    package org.apache.commons.convert;
020    
021    import java.io.IOException;
022    import java.io.InputStream;
023    import java.io.Reader;
024    import java.nio.ByteBuffer;
025    import java.nio.charset.Charset;
026    import java.sql.Blob;
027    import java.sql.Clob;
028    import java.text.DecimalFormat;
029    import java.text.SimpleDateFormat;
030    import java.util.Locale;
031    import java.util.UUID;
032    import java.util.regex.Pattern;
033    
034    /** Miscellaneous Converter classes. */
035    public class MiscConverters implements ConverterLoader {
036    
037        public void loadConverters() {
038            Converters.loadContainedConverters(MiscConverters.class);
039            Converters.registerConverter(new GenericToStringConverter<Locale>(Locale.class));
040            Converters.registerConverter(new GenericToStringConverter<UUID>(UUID.class));
041            Converters.registerConverter(new GenericToStringConverter<Pattern>(Pattern.class));
042        }
043    
044        /**
045         * An object that converts a <code>java.sql.Blob</code> to a
046         * byte array.
047         */
048        public static class BlobToByteArray extends AbstractConverter<Blob, byte[]> {
049            public BlobToByteArray() {
050                super(Blob.class, byte[].class);
051            }
052    
053            public byte[] convert(Blob obj) throws ConversionException {
054                InputStream inStream = null;
055                try {
056                    inStream = obj.getBinaryStream();
057                    int blobLength = (int) obj.length();
058                    byte[] byteBuffer = new byte[blobLength];
059                    int offset = 0;
060                    int bytesRead = inStream.read(byteBuffer, offset, blobLength);
061                    while (bytesRead > 0) {
062                        offset += bytesRead;
063                        bytesRead = inStream.read(byteBuffer, offset, blobLength);
064                    }
065                    return byteBuffer;
066                } catch (Exception e) {
067                    throw new ConversionException(e);
068                }
069                finally {
070                    if (inStream != null) {
071                        try {
072                            inStream.close();
073                        } catch (IOException e) {}
074                    }
075                }
076            }
077        }
078    
079        /**
080         * An object that converts a byte array to a
081         * <code>ByteBuffer</code>.
082         */
083        public static class ByteArrayToByteBuffer extends AbstractConverter<byte[], ByteBuffer> {
084            public ByteArrayToByteBuffer() {
085                super(byte[].class, ByteBuffer.class);
086            }
087    
088            public ByteBuffer convert(byte[] obj) throws ConversionException {
089                try {
090                    return ByteBuffer.wrap(obj);
091                } catch (Exception e) {
092                    throw new ConversionException(e);
093                }
094            }
095        }
096    
097        /**
098         * An object that converts a <code>ByteBuffer</code> to a
099         * byte array.
100         */
101        public static class ByteBufferToByteArray extends AbstractConverter<ByteBuffer, byte[]> {
102            public ByteBufferToByteArray() {
103                super(ByteBuffer.class, byte[].class);
104            }
105    
106            public byte[] convert(ByteBuffer obj) throws ConversionException {
107                try {
108                    return obj.hasArray() ? obj.array() : null;
109                } catch (Exception e) {
110                    throw new ConversionException(e);
111                }
112            }
113        }
114    
115        /**
116         * An object that converts a <code>Charset</code> to a
117         * character set name <code>String</code>.
118         */
119        public static class CharsetToString extends AbstractConverter<Charset, String> {
120            public CharsetToString() {
121                super(Charset.class, String.class);
122            }
123    
124            public String convert(Charset obj) throws ConversionException {
125                return obj.name();
126            }
127        }
128    
129        /**
130         * An object that converts a <code>java.sql.Clob</code> to a
131         * <code>String</code>.
132         */
133        public static class ClobToString extends AbstractConverter<Clob, String> {
134            public ClobToString() {
135                super(Clob.class, String.class);
136            }
137    
138            public String convert(Clob obj) throws ConversionException {
139                Reader clobReader = null;
140                try {
141                    clobReader = obj.getCharacterStream();
142                    int clobLength = (int) obj.length();
143                    char[] charBuffer = new char[clobLength];
144                    int offset = 0;
145                    int charsRead = clobReader.read(charBuffer, offset, clobLength);
146                    while (charsRead > 0) {
147                        offset += charsRead;
148                        charsRead = clobReader.read(charBuffer, offset, clobLength);
149                    }
150                    return new String(charBuffer);
151                } catch (Exception e) {
152                    throw new ConversionException(e);
153                }
154                finally {
155                    if (clobReader != null) {
156                        try {
157                            clobReader.close();
158                        } catch (IOException e) {}
159                    }
160                }
161            }
162        }
163    
164        /**
165         * An object that converts a <code>DecimalFormat</code> to a
166         * format pattern <code>String</code>.
167         */
168        public static class DecimalFormatToString extends AbstractConverter<DecimalFormat, String> {
169            public DecimalFormatToString() {
170                super(DecimalFormat.class, String.class);
171            }
172    
173            public String convert(DecimalFormat obj) throws ConversionException {
174                return obj.toPattern();
175            }
176        }
177    
178        public static class EnumToString extends AbstractConverter<Enum<?>, String> {
179            public EnumToString() {
180                super(Enum.class, String.class);
181            }
182    
183            public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
184                return Enum.class.isAssignableFrom(sourceClass) && String.class.isAssignableFrom(targetClass);
185            }
186    
187            public String convert(Enum<?> obj) throws ConversionException {
188                return obj.toString();
189            }
190    
191            public Class<? super Enum<?>> getSourceClass() {
192                return null;
193            }
194        }
195    
196        /**
197         * A class used for testing <code>ConverterLoader</code>
198         * implementations.
199         */
200        public static class NotAConverter {
201            protected NotAConverter() {
202                throw new Error("Should not be loaded");
203            }
204        }
205    
206        /**
207         * An object that converts a <code>SimpleDateFormat</code> to a
208         * format pattern <code>String</code>.
209         */
210        public static class SimpleDateFormatToString extends AbstractConverter<SimpleDateFormat, String> {
211            public SimpleDateFormatToString() {
212                super(SimpleDateFormat.class, String.class);
213            }
214    
215            public String convert(SimpleDateFormat obj) throws ConversionException {
216                return obj.toPattern();
217            }
218        }
219    
220        /**
221         * An object that converts a character set name <code>String</code> to a
222         * <code>Charset</code>.
223         */
224        public static class StringToCharset extends AbstractConverter<String, Charset> {
225            public StringToCharset() {
226                super(String.class, Charset.class);
227            }
228    
229            public Charset convert(String obj) throws ConversionException {
230                return Charset.forName(obj);
231            }
232        }
233    
234        /**
235         * An object that converts a format pattern <code>String</code> to a
236         * <code>DecimalFormat</code>.
237         */
238        public static class StringToDecimalFormat extends AbstractConverter<String, DecimalFormat> {
239            public StringToDecimalFormat() {
240                super(String.class, DecimalFormat.class);
241            }
242    
243            public DecimalFormat convert(String obj) throws ConversionException {
244                return new DecimalFormat(obj);
245            }
246        }
247    
248        private static class StringToEnum<E extends Enum<E>> extends AbstractConverter<String, E> {
249            public StringToEnum() {
250                super(String.class, Enum.class);
251            }
252    
253            public boolean canConvert(Class<?> sourceClass, Class<?> targetClass) {
254                return String.class.isAssignableFrom(sourceClass) && Enum.class.isAssignableFrom(targetClass);
255            }
256    
257            public E convert(String obj) throws ConversionException {
258                throw new UnsupportedOperationException();
259            }
260    
261            public Class<? super Enum> getTargetClass() {
262                return null;
263            }
264        }
265    
266        public static class StringToEnumConverterCreator implements ConverterCreator, ConverterLoader {
267            public <S, T> Converter<S, T> createConverter(Class<S> sourceClass, Class<T> targetClass) {
268                if (String.class == sourceClass && Enum.class.isAssignableFrom(targetClass)) {
269                    return Util.cast(new StringToEnum());
270                } else {
271                    return null;
272                }
273            }
274    
275            public void loadConverters() {
276                Converters.registerCreator(this);
277            }
278        }
279    
280        /**
281         * An object that converts a <code>Locale</code> ID
282         * <code>String</code> to a <code>Locale</code>.
283         */
284        public static class StringToLocale extends AbstractConverter<String, Locale> {
285            public StringToLocale() {
286                super(String.class, Locale.class);
287            }
288    
289            public Locale convert(String obj) throws ConversionException {
290                return new Locale(obj);
291            }
292        }
293    
294        /**
295         * An object that converts a pattern <code>String</code> to a
296         * <code>Pattern</code>.
297         */
298        public static class StringToRegexPattern extends AbstractConverter<String, Pattern> {
299            public StringToRegexPattern() {
300                super(String.class, Pattern.class);
301            }
302    
303            public Pattern convert(String obj) throws ConversionException {
304                return Pattern.compile(obj);
305            }
306        }
307    
308        /**
309         * An object that converts a format <code>String</code> to a
310         * <code>SimpleDateFormat</code>.
311         */
312        public static class StringToSimpleDateFormat extends AbstractConverter<String, SimpleDateFormat> {
313            public StringToSimpleDateFormat() {
314                super(String.class, SimpleDateFormat.class);
315            }
316    
317            public SimpleDateFormat convert(String obj) throws ConversionException {
318                return new SimpleDateFormat(obj);
319            }
320        }
321    
322        /**
323         * An object that converts a UUID <code>String</code> to a
324         * <code>UUID</code>.
325         */
326        public static class StringToUUID extends AbstractConverter<String, UUID> {
327            public StringToUUID() {
328                super(String.class, UUID.class);
329            }
330    
331            public UUID convert(String obj) throws ConversionException {
332                return UUID.fromString(obj);
333            }
334        }
335    }