diff --git a/spring-ai-core/src/main/java/org/springframework/ai/ResourceUtils.java b/spring-ai-core/src/main/java/org/springframework/ai/ResourceUtils.java index 5a5440e16..a3f54a67c 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/ResourceUtils.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/ResourceUtils.java @@ -21,10 +21,24 @@ import java.nio.charset.StandardCharsets; import org.springframework.core.io.DefaultResourceLoader; /** + * Miscellaneous Resource utility methods. Mainly for use within Spring AI + * * @author Christian Tzolov */ -public class ResourceUtils { +public abstract class ResourceUtils { + /** + * Retrieves the content of a resource as a UTF-8 encoded string. + * + * This method uses Spring's DefaultResourceLoader to load the resource from the given + * URI and then reads its content as a string using UTF-8 encoding. If an IOException + * occurs during reading, it is wrapped in a RuntimeException. + * @param uri The URI of the resource to be read. This can be any URI supported by + * Spring's ResourceLoader, such as "classpath:", "file:", or "http:". + * @return The content of the resource as a string. + * @throws RuntimeException If an error occurs while reading the resource. This + * exception wraps the original IOException. + */ public static String getText(String uri) { var resource = new DefaultResourceLoader().getResource(uri); try { diff --git a/spring-ai-core/src/main/java/org/springframework/ai/aot/AiRuntimeHints.java b/spring-ai-core/src/main/java/org/springframework/ai/aot/AiRuntimeHints.java index 8e0bd5cf6..39cd3cd8f 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/aot/AiRuntimeHints.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/aot/AiRuntimeHints.java @@ -32,16 +32,23 @@ import java.util.Set; import java.util.stream.Collectors; /** - * Native runtime hints. See other modules for their respective native runtime hints. + * Utility methods for creating native runtime hints. See other modules for their + * respective native runtime hints. * * @author Josh Long * @author Christian Tzolov * @author Mark Pollack */ -public class AiRuntimeHints { +public abstract class AiRuntimeHints { private static final Logger log = LoggerFactory.getLogger(AiRuntimeHints.class); + /** + * Finds classes in a package that are annotated with JsonInclude or have Jackson + * annotations. + * @param packageName The name of the package to search for annotated classes. + * @return A set of TypeReference objects representing the annotated classes found. + */ public static Set findJsonAnnotatedClassesInPackage(String packageName) { var annotationTypeFilter = new AnnotationTypeFilter(JsonInclude.class); TypeFilter typeFilter = (metadataReader, metadataReaderFactory) -> { @@ -58,10 +65,22 @@ public class AiRuntimeHints { return findClassesInPackage(packageName, typeFilter); } + /** + * Finds classes in a package that are annotated with JsonInclude or have Jackson + * annotations. + * @param packageClass The class in the package to search for annotated classes. + * @return A set of TypeReference objects representing the annotated classes found. + */ public static Set findJsonAnnotatedClassesInPackage(Class packageClass) { return findJsonAnnotatedClassesInPackage(packageClass.getPackageName()); } + /** + * Finds all classes in the specified package that match the given type filter. + * @param packageName The name of the package to scan for classes. + * @param typeFilter The type filter used to filter the scanned classes. + * @return A set of TypeReference objects representing the found classes. + */ public static Set findClassesInPackage(String packageName, TypeFilter typeFilter) { var classPathScanningCandidateComponentProvider = new ClassPathScanningCandidateComponentProvider(false); classPathScanningCandidateComponentProvider.addIncludeFilter(typeFilter); diff --git a/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/PromptMetadata.java b/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/PromptMetadata.java index 5e716921a..bbc32a791 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/PromptMetadata.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/chat/metadata/PromptMetadata.java @@ -48,7 +48,7 @@ public interface PromptMetadata extends Iterable PromptMetadata of(PromptFilterMetadata... array) { + static PromptMetadata of(PromptFilterMetadata... array) { return of(Arrays.asList(array)); } diff --git a/spring-ai-core/src/main/java/org/springframework/ai/document/Document.java b/spring-ai-core/src/main/java/org/springframework/ai/document/Document.java index ab105b031..268f7c2f4 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/document/Document.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/document/Document.java @@ -203,8 +203,8 @@ public class Document implements Content { @Override public String toString() { - return "Document{" + "id='" + id + '\'' + ", metadata=" + metadata + ", content='" + new String(content) + '\'' - + '}'; + return "Document{" + "id='" + id + '\'' + ", metadata=" + metadata + ", content='" + content + '\'' + ", media=" + + media + '}'; } } diff --git a/spring-ai-core/src/main/java/org/springframework/ai/document/id/JdkSha256HexIdGenerator.java b/spring-ai-core/src/main/java/org/springframework/ai/document/id/JdkSha256HexIdGenerator.java index c1591ccba..1302a6dd3 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/document/id/JdkSha256HexIdGenerator.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/document/id/JdkSha256HexIdGenerator.java @@ -72,9 +72,7 @@ public class JdkSha256HexIdGenerator implements IdGenerator { private byte[] serializeToBytes(Object... contents) { Assert.notNull(contents, "Contents must not be null"); - ByteArrayOutputStream byteOut = null; - try { - byteOut = new ByteArrayOutputStream(); + try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream()) { ObjectOutputStream out = new ObjectOutputStream(byteOut); for (Object content : contents) { out.writeObject(content); @@ -84,16 +82,6 @@ public class JdkSha256HexIdGenerator implements IdGenerator { catch (Exception e) { throw new RuntimeException("Failed to serialize", e); } - finally { - if (byteOut != null) { - try { - byteOut.close(); - } - catch (Exception e) { - // ignore - } - } - } } MessageDigest getMessageDigest() { diff --git a/spring-ai-core/src/main/java/org/springframework/ai/model/ModelOptionsUtils.java b/spring-ai-core/src/main/java/org/springframework/ai/model/ModelOptionsUtils.java index bb48320b6..d9b2bda50 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/model/ModelOptionsUtils.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/model/ModelOptionsUtils.java @@ -57,22 +57,18 @@ import org.springframework.util.CollectionUtils; * @author Christian Tzolov * @since 0.8.0 */ -public final class ModelOptionsUtils { +public abstract class ModelOptionsUtils { - public final static ObjectMapper OBJECT_MAPPER = new ObjectMapper() + public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper() .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS) .registerModule(new JavaTimeModule()); - private final static List BEAN_MERGE_FIELD_EXCISIONS = List.of("class"); + private static final List BEAN_MERGE_FIELD_EXCISIONS = List.of("class"); - private static ConcurrentHashMap, List> REQUEST_FIELD_NAMES_PER_CLASS = new ConcurrentHashMap, List>(); + private static final ConcurrentHashMap, List> REQUEST_FIELD_NAMES_PER_CLASS = new ConcurrentHashMap, List>(); - private static AtomicReference SCHEMA_GENERATOR_CACHE = new AtomicReference<>(); - - private ModelOptionsUtils() { - - } + private static final AtomicReference SCHEMA_GENERATOR_CACHE = new AtomicReference<>(); /** * Converts the given JSON string to a Map of String and Object. diff --git a/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java b/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java index d065a5fe4..bfa9c9c3c 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallbackWrapper.java @@ -81,7 +81,7 @@ public class FunctionCallbackWrapper extends AbstractFunctionCallback responseConverter = (response) -> ModelOptionsUtils.toJsonString(response); + private Function responseConverter = ModelOptionsUtils::toJsonString; private String inputTypeSchema; diff --git a/spring-ai-core/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java b/spring-ai-core/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java index f35411b15..1fa0736d3 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/model/function/TypeResolverHelper.java @@ -25,18 +25,37 @@ import net.jodah.typetools.TypeResolver; import org.springframework.cloud.function.context.catalog.FunctionTypeUtils; /** + * A utility class that provides methods for resolving types and classes related to + * functions. + * * @author Christian Tzolov */ -public class TypeResolverHelper { +public abstract class TypeResolverHelper { + /** + * Returns the input class of a given function class. + * @param functionClass The function class. + * @return The input class of the function. + */ public static Class getFunctionInputClass(Class> functionClass) { return getFunctionArgumentClass(functionClass, 0); } + /** + * Returns the output class of a given function class. + * @param functionClass The function class. + * @return The output class of the function. + */ public static Class getFunctionOutputClass(Class> functionClass) { return getFunctionArgumentClass(functionClass, 1); } + /** + * Retrieves the class of a specific argument in a given function class. + * @param functionClass The function class. + * @param argumentIndex The index of the argument whose class should be retrieved. + * @return The class of the specified function argument. + */ public static Class getFunctionArgumentClass(Class> functionClass, int argumentIndex) { Type type = TypeResolver.reify(Function.class, functionClass); @@ -46,19 +65,41 @@ public class TypeResolverHelper { return toRawClass(argumentType); } + /** + * Returns the input type of a given function class. + * @param functionClass The class of the function. + * @return The input type of the function. + */ public static Type getFunctionInputType(Class> functionClass) { return getFunctionArgumentType(functionClass, 0); } + /** + * Retrieves the output type of a given function class. + * @param functionClass The function class. + * @return The output type of the function. + */ public static Type getFunctionOutputType(Class> functionClass) { return getFunctionArgumentType(functionClass, 1); } + /** + * Retrieves the type of a specific argument in a given function class. + * @param functionClass The function class. + * @param argumentIndex The index of the argument whose type should be retrieved. + * @return The type of the specified function argument. + */ public static Type getFunctionArgumentType(Class> functionClass, int argumentIndex) { Type functionType = TypeResolver.reify(Function.class, functionClass); return getFunctionArgumentType(functionType, argumentIndex); } + /** + * Retrieves the type of a specific argument in a given function type. + * @param functionType The function type. + * @param argumentIndex The index of the argument whose type should be retrieved. + * @return The type of the specified function argument. + */ public static Type getFunctionArgumentType(Type functionType, int argumentIndex) { // Resolves: https://github.com/spring-projects/spring-ai/issues/726