001/* 002 * Copyright 2022-2026 Revetware LLC. 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 017package com.soklet.converter; 018 019import org.jspecify.annotations.NonNull; 020import org.jspecify.annotations.Nullable; 021 022import javax.annotation.concurrent.NotThreadSafe; 023import java.lang.reflect.Type; 024import java.util.Optional; 025 026import static java.util.Objects.requireNonNull; 027 028/** 029 * Thrown if an error occurs during value conversion. 030 * <p> 031 * For example, a {@link ValueConverter} for 'from' type {@link String} and 'to' type {@link Integer} 032 * might throw this exception if the 'from' value is {@code "abc"}. 033 * 034 * @author <a href="https://www.revetkn.com">Mark Allen</a> 035 */ 036@NotThreadSafe 037public class ValueConversionException extends Exception { 038 @NonNull 039 private final Type fromType; 040 @Nullable 041 private final Object fromValue; 042 @NonNull 043 private final Type toType; 044 045 /** 046 * Creates an exception that describes the value conversion error. 047 * 048 * @param message a message describing the error 049 * @param fromType the 'from' type 050 * @param fromValue the value supplied for the 'from' type 051 * @param toType the 'to' type 052 */ 053 public ValueConversionException(@Nullable String message, 054 @NonNull Type fromType, 055 @Nullable Object fromValue, 056 @NonNull Type toType) { 057 super(message); 058 059 requireNonNull(fromType); 060 requireNonNull(toType); 061 062 this.fromType = fromType; 063 this.fromValue = fromValue; 064 this.toType = toType; 065 } 066 067 /** 068 * Creates an exception that describes the value conversion error. 069 * 070 * @param cause the underlying exception that caused this one to be thrown 071 * @param fromType the 'from' type 072 * @param fromValue the value supplied for the 'from' type 073 * @param toType the 'to' type 074 */ 075 public ValueConversionException(@Nullable Throwable cause, 076 @NonNull Type fromType, 077 @Nullable Object fromValue, 078 @NonNull Type toType) { 079 super(cause); 080 081 requireNonNull(fromType); 082 requireNonNull(toType); 083 084 this.fromType = fromType; 085 this.fromValue = fromValue; 086 this.toType = toType; 087 } 088 089 /** 090 * Creates an exception that describes the value conversion error. 091 * 092 * @param message a message describing the error 093 * @param cause the underlying exception that caused this one to be thrown 094 * @param fromType the 'from' type 095 * @param fromValue the value supplied for the 'from' type 096 * @param toType the 'to' type 097 */ 098 public ValueConversionException(@Nullable String message, 099 @Nullable Throwable cause, 100 @NonNull Type fromType, 101 @Nullable Object fromValue, 102 @NonNull Type toType) { 103 super(message, cause); 104 105 requireNonNull(fromType); 106 requireNonNull(toType); 107 108 this.fromType = fromType; 109 this.fromValue = fromValue; 110 this.toType = toType; 111 } 112 113 /** 114 * The 'from' type of the failed {@link ValueConverter}. 115 * 116 * @return the 'from' type 117 */ 118 @NonNull 119 public Type getFromType() { 120 return this.fromType; 121 } 122 123 /** 124 * The 'from' value of the failed {@link ValueConverter}. 125 * 126 * @return the 'from' value that could not be converted to the 'to' type 127 */ 128 @NonNull 129 public Optional<Object> getFromValue() { 130 return Optional.ofNullable(this.fromValue); 131 } 132 133 /** 134 * The 'to' type of the failed {@link ValueConverter}. 135 * 136 * @return the 'to' type 137 */ 138 @NonNull 139 public Type getToType() { 140 return this.toType; 141 } 142}