001 /* 002 * Copyright 2004 The Apache Software Foundation 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.apache.commons.convert.conversion; 017 018 import org.apache.commons.convert.Conversion; 019 import org.apache.commons.convert.ConversionFactory; 020 import org.apache.commons.convert.Converter; 021 022 /** 023 * A utility class for decorating conversions and factories with default value behaviour. 024 * <p> 025 * Each public static method on this class will decorate the input conversion/factory 026 * with additional behaviour. Depending on the method it may return a default value in 027 * the case of an exception or null value 028 * <p> 029 * To use this facility, create an instance of the conversion/factory as normal. 030 * Then pass it to one of the static methods on this class. 031 * Finally add it as per normal to the <code>ConverterRegistry</code>. 032 * 033 * @author Stephen Colebourne 034 * @author Oliver Heger 035 * @version $Id: DefaultValueDecorator.java 155441 2005-02-26 13:19:22Z dirkv $ 036 * @since 1.0 037 */ 038 public class DefaultValueDecorator { 039 040 /** 041 * Restricted constructor. 042 */ 043 protected DefaultValueDecorator() { 044 } 045 046 //----------------------------------------------------------------------- 047 /** 048 * Creates a Conversion that decorates the original and adds behaviour to 049 * return a default value when the conversion results in null. 050 * 051 * @param conversion the conversion to decorate, not null 052 * @param defaultValue the value to return if conversion result is null 053 * @return the decorated conversion 054 */ 055 public static Conversion defaultNullResult(Conversion conversion, Object defaultValue) { 056 checkNotNull(conversion); 057 return new DefaultNullResultConversion(conversion, defaultValue); 058 } 059 060 /** 061 * Creates a Conversion that decorates the original and adds behaviour to 062 * return a default value when the conversion input is null. 063 * 064 * @param conversion the conversion to decorate, not null 065 * @param defaultValue the value to return if conversion input is null 066 * @return the decorated conversion 067 */ 068 public static Conversion defaultNullInput(Conversion conversion, Object defaultValue) { 069 checkNotNull(conversion); 070 return new DefaultNullInputConversion(conversion, defaultValue); 071 } 072 073 /** 074 * Creates a Conversion that decorates the original and adds behaviour to 075 * return a default value when the conversion throws an exception. 076 * 077 * @param conversion the conversion to decorate, not null 078 * @param defaultValue the value to return if conversion throws an exception 079 * @return the decorated conversion 080 */ 081 public static Conversion defaultException(Conversion conversion, Object defaultValue) { 082 checkNotNull(conversion); 083 return new DefaultExceptionConversion(conversion, defaultValue); 084 } 085 086 /** 087 * Creates a Conversion that decorates the original and adds behaviour to 088 * return a default value for null input, null result and when an exception occurs. 089 * 090 * @param conversion the conversion to decorate, not null 091 * @param defaultValue the default value to return 092 * @return the decorated conversion 093 */ 094 public static Conversion defaultNullAndException(Conversion conversion, Object defaultValue) { 095 checkNotNull(conversion); 096 return new DefaultNullExceptionConversion(conversion, defaultValue); 097 } 098 099 //----------------------------------------------------------------------- 100 /** 101 * Creates a ConversionFactory that decorates the original and adds behaviour to 102 * return a default value when the conversion results in null. 103 * 104 * @param factory the factory to decorate, not null 105 * @param defaultValue the value to return if conversion result is null 106 * @return the decorated factory 107 */ 108 public static ConversionFactory defaultNullResult(ConversionFactory factory, Object defaultValue) { 109 checkNotNull(factory); 110 return new DefaultNullResultConversionFactory(factory, defaultValue); 111 } 112 113 /** 114 * Creates a ConversionFactory that decorates the original and adds behaviour to 115 * return a default value when the conversion input is null. 116 * 117 * @param factory the factory to decorate, not null 118 * @param defaultValue the value to return if conversion input is null 119 * @return the decorated factory 120 */ 121 public static ConversionFactory defaultNullInput(ConversionFactory factory, Object defaultValue) { 122 checkNotNull(factory); 123 return new DefaultNullInputConversionFactory(factory, defaultValue); 124 } 125 126 /** 127 * Creates a ConversionFactory that decorates the original and adds behaviour to 128 * return a default value when the conversion throws an exception. 129 * 130 * @param factory the factory to decorate, not null 131 * @param defaultValue the value to return if conversion throws an exception 132 * @return the decorated factory 133 */ 134 public static ConversionFactory defaultException(ConversionFactory factory, Object defaultValue) { 135 checkNotNull(factory); 136 return new DefaultExceptionConversionFactory(factory, defaultValue); 137 } 138 139 /** 140 * Creates a ConversionFactory that decorates the original and adds behaviour to 141 * return a default value for null input, null result and when an exception occurs. 142 * 143 * @param factory the factory to decorate, not null 144 * @param defaultValue the default value to return 145 * @return the decorated factory 146 */ 147 public static ConversionFactory defaultNullAndException(ConversionFactory factory, Object defaultValue) { 148 checkNotNull(factory); 149 return new DefaultNullExceptionConversionFactory(factory, defaultValue); 150 } 151 152 //----------------------------------------------------------------------- 153 /** 154 * Checks whether the input conversion is null and throws an exception. 155 * 156 * @param conversion the conversion to check 157 */ 158 private static void checkNotNull(Conversion conversion) { 159 if (conversion == null) { 160 throw new IllegalArgumentException("Conversion must not be null"); 161 } 162 } 163 164 /** 165 * Checks whether the input factory is null and throws an exception. 166 * 167 * @param factory the factory to check 168 */ 169 private static void checkNotNull(ConversionFactory factory) { 170 if (factory == null) { 171 throw new IllegalArgumentException("ConversionFactory must not be null"); 172 } 173 } 174 175 //----------------------------------------------------------------------- 176 /** 177 * Abstract base class for default value decorators. 178 */ 179 abstract static class AbstractDefaultConversion implements Conversion { 180 181 /** The decorated conversion */ 182 private final Conversion conversion; 183 /** The default value to return */ 184 private final Object defaultValue; 185 186 /** 187 * Constructor. 188 * 189 * @param conversion the conversion to decorate, not null 190 * @param defaultValue the default value to return 191 */ 192 AbstractDefaultConversion(Conversion conversion, Object defaultValue) { 193 super(); 194 this.conversion = conversion; 195 this.defaultValue = defaultValue; 196 } 197 198 /** 199 * Returns the type to convert from. 200 * 201 * @return the Class object representing the class to convert from 202 */ 203 public Class getFromType() { 204 return getDecoratedConversion().getFromType(); 205 } 206 207 /** 208 * Returns the type to convert to. 209 * 210 * @return the Class object representing the class to convert to 211 */ 212 public Class getToType() { 213 return getDecoratedConversion().getToType(); 214 } 215 216 /** 217 * Gets the conversion being decorated. 218 * 219 * @return the decorated conversion 220 */ 221 public Conversion getDecoratedConversion() { 222 return conversion; 223 } 224 225 /** 226 * Gets the default value to be returned. 227 * 228 * @return the default value 229 */ 230 public Object getDefaultValue() { 231 return defaultValue; 232 } 233 234 /** 235 * Gets a suitable debugging string. 236 * 237 * @return a debugging string 238 */ 239 public String toString() { 240 String str = getDecoratedConversion().toString(); 241 return str.substring(0, str.length() - 1) + ",default=" + getDefaultValue() + "]"; 242 } 243 } 244 245 //----------------------------------------------------------------------- 246 /** 247 * Implement the default null result behaviour. 248 */ 249 static class DefaultNullResultConversion extends AbstractDefaultConversion { 250 251 /** 252 * Constructs a null result conversion. 253 * 254 * @param conversion the conversion to decorate, not null 255 * @param defaultValue the value to return if conversion result is null 256 */ 257 DefaultNullResultConversion(Conversion conversion, Object defaultValue) { 258 super(conversion, defaultValue); 259 } 260 261 /** 262 * Performs the conversion by delegating to the original conversion and 263 * then handling the default value. 264 * 265 * @param value the object to be converted 266 * @param converter the associated converter 267 * @return the result of the conversion 268 * @throws Exception if conversion fails, use ConversionException if creating 269 * a new exception, otherwise just allow exceptions to be thrown 270 */ 271 public Object convert(Object value, Converter converter) throws Exception { 272 Object result = getDecoratedConversion().convert(value, converter); 273 if (result == null) { 274 return getDefaultValue(); 275 } 276 return result; 277 } 278 } 279 280 //----------------------------------------------------------------------- 281 /** 282 * Implement the default null input behaviour. 283 */ 284 static class DefaultNullInputConversion extends AbstractDefaultConversion { 285 286 /** 287 * Constructs a null input conversion. 288 * 289 * @param conversion the conversion to decorate, not null 290 * @param defaultValue the value to return if conversion input is null 291 */ 292 DefaultNullInputConversion(Conversion conversion, Object defaultValue) { 293 super(conversion, defaultValue); 294 } 295 296 /** 297 * Performs the conversion by checking for null, then delegating to the 298 * original conversion. 299 * 300 * @param value the object to be converted 301 * @param converter the associated converter 302 * @return the result of the conversion 303 * @throws Exception if conversion fails, use ConversionException if creating 304 * a new exception, otherwise just allow exceptions to be thrown 305 */ 306 public Object convert(Object value, Converter converter) throws Exception { 307 if (value == null) { 308 return getDefaultValue(); 309 } 310 return getDecoratedConversion().convert(value, converter); 311 } 312 } 313 314 //----------------------------------------------------------------------- 315 /** 316 * Implement the default on exception behaviour. 317 */ 318 static class DefaultExceptionConversion extends AbstractDefaultConversion { 319 320 /** 321 * Constructs a default on exception conversion. 322 * 323 * @param conversion the conversion to decorate, not null 324 * @param defaultValue the value to return if conversion throws an exception 325 */ 326 DefaultExceptionConversion(Conversion conversion, Object defaultValue) { 327 super(conversion, defaultValue); 328 } 329 330 /** 331 * Performs the conversion by delegating to the original conversion and 332 * handling the default value. 333 * 334 * @param value the object to be converted 335 * @param converter the associated converter 336 * @return the result of the conversion 337 */ 338 public Object convert(Object value, Converter converter) { 339 try { 340 return getDecoratedConversion().convert(value, converter); 341 } catch (Exception ex) { 342 return getDefaultValue(); 343 } 344 } 345 } 346 347 //----------------------------------------------------------------------- 348 /** 349 * Implement the default on exception behaviour. 350 */ 351 static class DefaultNullExceptionConversion extends AbstractDefaultConversion { 352 353 /** 354 * Constructs a default on nulls and exception conversion. 355 * 356 * @param conversion the conversion to decorate, not null 357 * @param defaultValue the default value to return 358 */ 359 DefaultNullExceptionConversion(Conversion conversion, Object defaultValue) { 360 super(conversion, defaultValue); 361 } 362 363 /** 364 * Performs the conversion by delegating to the original conversion and 365 * handling the default value. 366 * 367 * @param value the object to be converted 368 * @param converter the associated converter 369 * @return the result of the conversion 370 */ 371 public Object convert(Object value, Converter converter) { 372 if (value == null) { 373 return getDefaultValue(); 374 } 375 try { 376 Object result = getDecoratedConversion().convert(value, converter); 377 if (result == null) { 378 return getDefaultValue(); 379 } 380 return result; 381 } catch (Exception ex) { 382 return getDefaultValue(); 383 } 384 } 385 } 386 387 //----------------------------------------------------------------------- 388 /** 389 * Implement the default null result behaviour. 390 */ 391 abstract static class AbstractDefaultConversionFactory implements ConversionFactory { 392 393 /** The decorated factory */ 394 private final ConversionFactory factory; 395 /** The default value to return */ 396 private final Object defaultValue; 397 398 /** 399 * Constructor. 400 * 401 * @param factory the factory to decorate, not null 402 * @param defaultValue the default value to return 403 */ 404 AbstractDefaultConversionFactory(ConversionFactory factory, Object defaultValue) { 405 super(); 406 this.factory = factory; 407 this.defaultValue = defaultValue; 408 } 409 410 /** 411 * Gets an indicator as to how well the factory matches. 412 * 413 * @param value the value to be converted 414 * @param fromType the type to be converted from 415 * @param toType the type to be converted to 416 * @return a percentage value for the appropriateness of this class 417 */ 418 public int getMatchPercent(Object value, Class fromType, Class toType) { 419 return getDecoratedConversionFactory().getMatchPercent(value, fromType, toType); 420 } 421 422 /** 423 * Creates a conversion instance for the specified conversion. 424 * This implementation lets the decorated factory create an instance. 425 * This instance is then decorated with defaulting behaviour. 426 * 427 * @param value the value to be converted 428 * @param fromType the type to convert from 429 * @param toType the type to convert to 430 * @return a conversion instance 431 */ 432 public Conversion getInstance(Object value, Class fromType, Class toType) { 433 Conversion conversion = getDecoratedConversionFactory().getInstance(value, fromType, toType); 434 return createConversion(conversion, getDefaultValue()); 435 } 436 437 /** 438 * Creates a new decorated conversion. 439 * 440 * @param conversion the conversion to decorate 441 * @param defaultValue the default value 442 * @return a new decorated conversion 443 */ 444 protected abstract Conversion createConversion(Conversion conversion, Object defaultValue); 445 446 /** 447 * Gets the factory being decorated. 448 * 449 * @return the decorated factory 450 */ 451 public ConversionFactory getDecoratedConversionFactory() { 452 return factory; 453 } 454 455 /** 456 * Gets the default value to be returned. 457 * 458 * @return the default value 459 */ 460 public Object getDefaultValue() { 461 return defaultValue; 462 } 463 } 464 465 //----------------------------------------------------------------------- 466 /** 467 * Implement the default null result behaviour. 468 */ 469 static class DefaultNullResultConversionFactory extends AbstractDefaultConversionFactory { 470 471 /** 472 * Constructs a null result factory. 473 * 474 * @param factory the factory to decorate, not null 475 * @param defaultValue the default value to return 476 */ 477 DefaultNullResultConversionFactory(ConversionFactory factory, Object defaultValue) { 478 super(factory, defaultValue); 479 } 480 481 /** 482 * Creates a new decorated conversion. 483 * 484 * @param conversion the conversion to decorate 485 * @param defaultValue the default value 486 * @return a new decorated conversion 487 */ 488 protected Conversion createConversion(Conversion conversion, Object defaultValue) { 489 return new DefaultNullResultConversion(conversion, defaultValue); 490 } 491 } 492 493 //----------------------------------------------------------------------- 494 /** 495 * Implement the default null input behaviour. 496 */ 497 static class DefaultNullInputConversionFactory extends AbstractDefaultConversionFactory { 498 499 /** 500 * Constructs a null input factory. 501 * 502 * @param factory the factory to decorate, not null 503 * @param defaultValue the default value to return 504 */ 505 DefaultNullInputConversionFactory(ConversionFactory factory, Object defaultValue) { 506 super(factory, defaultValue); 507 } 508 509 /** 510 * Creates a new decorated conversion. 511 * 512 * @param conversion the conversion to decorate 513 * @param defaultValue the default value 514 * @return a new decorated conversion 515 */ 516 protected Conversion createConversion(Conversion conversion, Object defaultValue) { 517 return new DefaultNullInputConversion(conversion, defaultValue); 518 } 519 } 520 521 //----------------------------------------------------------------------- 522 /** 523 * Implement the default on exception behaviour. 524 */ 525 static class DefaultExceptionConversionFactory extends AbstractDefaultConversionFactory { 526 527 /** 528 * Constructs a null result factory. 529 * 530 * @param factory the factory to decorate, not null 531 * @param defaultValue the default value to return 532 */ 533 DefaultExceptionConversionFactory(ConversionFactory factory, Object defaultValue) { 534 super(factory, defaultValue); 535 } 536 537 /** 538 * Creates a new decorated conversion. 539 * 540 * @param conversion the conversion to decorate 541 * @param defaultValue the default value 542 * @return a new decorated conversion 543 */ 544 protected Conversion createConversion(Conversion conversion, Object defaultValue) { 545 return new DefaultExceptionConversion(conversion, defaultValue); 546 } 547 } 548 549 //----------------------------------------------------------------------- 550 /** 551 * Implement the default on nulls and exceptions behaviour. 552 */ 553 static class DefaultNullExceptionConversionFactory extends AbstractDefaultConversionFactory { 554 555 /** 556 * Constructs a null result factory. 557 * 558 * @param factory the factory to decorate, not null 559 * @param defaultValue the default value to return 560 */ 561 DefaultNullExceptionConversionFactory(ConversionFactory factory, Object defaultValue) { 562 super(factory, defaultValue); 563 } 564 565 /** 566 * Creates a new decorated conversion. 567 * 568 * @param conversion the conversion to decorate 569 * @param defaultValue the default value 570 * @return a new decorated conversion 571 */ 572 protected Conversion createConversion(Conversion conversion, Object defaultValue) { 573 return new DefaultNullExceptionConversion(conversion, defaultValue); 574 } 575 } 576 577 }