11package com .github .codeboyzhou .mcp .declarative .util ;
22
3- import com .github .codeboyzhou .mcp .declarative .enums .JsonSchemaDataType ;
3+ import java .util .Map ;
4+ import java .util .concurrent .ConcurrentHashMap ;
5+ import java .util .function .Function ;
6+ import org .jetbrains .annotations .NotNull ;
7+ import org .jetbrains .annotations .Nullable ;
48import org .jetbrains .annotations .VisibleForTesting ;
59
610/**
1014 */
1115public final class TypeConverter {
1216
17+ /** Map of Java classes to their corresponding type conversion functions. */
18+ private static final Map <Class <?>, Function <@ NotNull String , @ NotNull Object >> CLASS_CONVERTERS ;
19+
20+ /** Map of Java classes to their default values. */
21+ private static final Map <Class <?>, Object > DEFAULT_VALUES ;
22+
23+ static {
24+ CLASS_CONVERTERS = new ConcurrentHashMap <>();
25+ DEFAULT_VALUES = new ConcurrentHashMap <>();
26+ initializeClassConverters ();
27+ initializeDefaultValues ();
28+ }
29+
1330 /**
1431 * Private constructor to prevent instantiation of the utility class.
1532 *
@@ -20,121 +37,78 @@ public final class TypeConverter {
2037 throw new UnsupportedOperationException ("Utility class should not be instantiated" );
2138 }
2239
40+ /** Initializes the map of Java classes to their corresponding type conversion functions. */
41+ private static void initializeClassConverters () {
42+ CLASS_CONVERTERS .put (String .class , value -> value );
43+ CLASS_CONVERTERS .put (int .class , Integer ::parseInt );
44+ CLASS_CONVERTERS .put (Integer .class , Integer ::parseInt );
45+ CLASS_CONVERTERS .put (long .class , Long ::parseLong );
46+ CLASS_CONVERTERS .put (Long .class , Long ::parseLong );
47+ CLASS_CONVERTERS .put (float .class , Float ::parseFloat );
48+ CLASS_CONVERTERS .put (Float .class , Float ::parseFloat );
49+ CLASS_CONVERTERS .put (double .class , Double ::parseDouble );
50+ CLASS_CONVERTERS .put (Double .class , Double ::parseDouble );
51+ CLASS_CONVERTERS .put (Number .class , TypeConverter ::parseNumber );
52+ CLASS_CONVERTERS .put (boolean .class , Boolean ::parseBoolean );
53+ CLASS_CONVERTERS .put (Boolean .class , Boolean ::parseBoolean );
54+ }
55+
56+ /** Initializes the map of Java classes to their default values. */
57+ private static void initializeDefaultValues () {
58+ DEFAULT_VALUES .put (String .class , StringHelper .EMPTY );
59+ DEFAULT_VALUES .put (int .class , 0 );
60+ DEFAULT_VALUES .put (Integer .class , 0 );
61+ DEFAULT_VALUES .put (long .class , 0L );
62+ DEFAULT_VALUES .put (Long .class , 0L );
63+ DEFAULT_VALUES .put (float .class , 0.0F );
64+ DEFAULT_VALUES .put (Float .class , 0.0F );
65+ DEFAULT_VALUES .put (double .class , 0.0 );
66+ DEFAULT_VALUES .put (Double .class , 0.0 );
67+ DEFAULT_VALUES .put (Number .class , 0.0 );
68+ DEFAULT_VALUES .put (boolean .class , false );
69+ DEFAULT_VALUES .put (Boolean .class , false );
70+ }
71+
2372 /**
24- * Converts the given value to the specified target type. If the value is null, returns the
25- * default value for the target type .
73+ * Parses the given string as a number, preferring double precision if the string contains a dot,
74+ * and falling back to integer or long if not .
2675 *
27- * @param value the value to convert
28- * @param targetType the target type to convert to
29- * @return the converted value
76+ * @param number the string representation of the number
77+ * @return the parsed number
3078 */
31- public static Object convert (Object value , Class <?> targetType ) {
32- if (value == null ) {
33- return getDefaultValue (targetType );
79+ private static Number parseNumber (@ NotNull String number ) {
80+ // Parse as a double if it contains a dot
81+ if (number .contains (StringHelper .DOT )) {
82+ return Double .parseDouble (number );
3483 }
3584
36- final String valueAsString = value .toString ();
37-
38- if (targetType == String .class ) {
39- return valueAsString ;
40- }
41- if (targetType == int .class || targetType == Integer .class ) {
42- return Integer .parseInt (valueAsString );
43- }
44- if (targetType == long .class || targetType == Long .class ) {
45- return Long .parseLong (valueAsString );
46- }
47- if (targetType == float .class || targetType == Float .class ) {
48- return Float .parseFloat (valueAsString );
85+ // If it doesn't contain a dot, try to parse as an integer first
86+ try {
87+ return Integer .parseInt (number );
88+ } catch (NumberFormatException e ) {
89+ // If it's not an integer, try to parse as a long
90+ return Long .parseLong (number );
4991 }
50- if (targetType == double .class || targetType == Double .class ) {
51- return Double .parseDouble (valueAsString );
52- }
53- if (targetType == boolean .class || targetType == Boolean .class ) {
54- return Boolean .parseBoolean (valueAsString );
55- }
56-
57- return valueAsString ;
5892 }
5993
6094 /**
61- * Converts the given value to the specified target type based on the JSON schema type. If the
62- * value is null, returns the default value for the JSON schema type.
95+ * Converts the given value to the specified target type. If the value is null, returns the
96+ * default value for the target type.
6397 *
6498 * @param value the value to convert
65- * @param jsonSchemaType the JSON schema type to convert to
99+ * @param targetType the target type to convert to
66100 * @return the converted value
67101 */
68- public static Object convert (Object value , String jsonSchemaType ) {
102+ public static Object convert (@ Nullable Object value , Class <?> targetType ) {
69103 if (value == null ) {
70- return getDefaultValue ( jsonSchemaType );
104+ return DEFAULT_VALUES . get ( targetType );
71105 }
72106
73- final String valueAsString = value .toString ();
74-
75- if (JsonSchemaDataType .STRING .getType ().equals (jsonSchemaType )) {
76- return valueAsString ;
77- }
78- if (JsonSchemaDataType .INTEGER .getType ().equals (jsonSchemaType )) {
79- return Integer .parseInt (valueAsString );
80- }
81- if (JsonSchemaDataType .NUMBER .getType ().equals (jsonSchemaType )) {
82- return Double .parseDouble (valueAsString );
83- }
84- if (JsonSchemaDataType .BOOLEAN .getType ().equals (jsonSchemaType )) {
85- return Boolean .parseBoolean (valueAsString );
86- }
87-
88- return valueAsString ;
89- }
90-
91- /**
92- * Returns the default value for the specified type.
93- *
94- * @param type the type to get the default value for
95- * @return the default value for the specified type
96- */
97- private static Object getDefaultValue (Class <?> type ) {
98- if (type == String .class ) {
99- return StringHelper .EMPTY ;
100- }
101- if (type == int .class || type == Integer .class ) {
102- return 0 ;
107+ if (CLASS_CONVERTERS .containsKey (targetType )) {
108+ Function <String , Object > converter = CLASS_CONVERTERS .get (targetType );
109+ return converter .apply (value .toString ());
103110 }
104- if (type == long .class || type == Long .class ) {
105- return 0L ;
106- }
107- if (type == float .class || type == Float .class ) {
108- return 0.0f ;
109- }
110- if (type == double .class || type == Double .class ) {
111- return 0.0 ;
112- }
113- if (type == boolean .class || type == Boolean .class ) {
114- return false ;
115- }
116- return null ;
117- }
118111
119- /**
120- * Returns the default value for the specified JSON schema type.
121- *
122- * @param jsonSchemaType the JSON schema type to get the default value for
123- * @return the default value for the specified JSON schema type
124- */
125- private static Object getDefaultValue (String jsonSchemaType ) {
126- if (JsonSchemaDataType .STRING .getType ().equalsIgnoreCase (jsonSchemaType )) {
127- return StringHelper .EMPTY ;
128- }
129- if (JsonSchemaDataType .INTEGER .getType ().equalsIgnoreCase (jsonSchemaType )) {
130- return 0 ;
131- }
132- if (JsonSchemaDataType .NUMBER .getType ().equalsIgnoreCase (jsonSchemaType )) {
133- return 0.0 ;
134- }
135- if (JsonSchemaDataType .BOOLEAN .getType ().equalsIgnoreCase (jsonSchemaType )) {
136- return false ;
137- }
138- return null ;
112+ return value ;
139113 }
140114}
0 commit comments