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 }