From be6a8c853e963c7d28fcf53e8826cf45a61231f5 Mon Sep 17 00:00:00 2001 From: Konrad Neitzel Date: Fri, 11 Apr 2025 21:55:18 +0200 Subject: [PATCH 1/8] Updated Injection Classes. Unit Tests still required. --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 02087dc..7063983 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,10 @@ Some JavaFX additions. Some example programs that use the fx component +### gson + +TypeAdapter for gson. + ### log4j Stuff for log4j (Version 1). Please use log4j2 if you want to use log4j! (Or log with slf4j as I do in all other modules!) -- 2.47.1 From 2b6003877427497ec41e892aaa917e50c0c9ff66 Mon Sep 17 00:00:00 2001 From: Konrad Neitzel Date: Sat, 12 Apr 2025 20:38:20 +0200 Subject: [PATCH 2/8] Binding and FxmlComponent controls to allow bindings and loading of FXML Components. --- fx/ideas.md | 15 ++++ .../fx/component/controls/Binding.java | 67 ++++++++++++++ .../fx/component/controls/FxmlComponent.java | 90 +++++++++++++++++++ .../fx/component/model/BindingData.java | 82 +++++++++++++++++ 4 files changed, 254 insertions(+) create mode 100644 fx/ideas.md create mode 100644 fx/src/main/java/de/neitzel/fx/component/controls/Binding.java create mode 100644 fx/src/main/java/de/neitzel/fx/component/controls/FxmlComponent.java create mode 100644 fx/src/main/java/de/neitzel/fx/component/model/BindingData.java diff --git a/fx/ideas.md b/fx/ideas.md new file mode 100644 index 0000000..8c180d5 --- /dev/null +++ b/fx/ideas.md @@ -0,0 +1,15 @@ +# Ideen + +# Bindings +Bindngs kommen über ein spezielles Binding Control, das dann notwendige Bindings beinhaltet. + +Da kann dann auch eine eigene Logik zur Erkennung des Bindings erfolgen oder zusätziche Informationen bezüglich notwendiger Elemente in dem ViewModel + +# FXMLComponent +Dient dem Laden einer Komponente und bekommt dazu das fxml, die Daten und ggf. auch eine ModelView. + +# ModelView generieren +Damit eine ModelView nicht ständig manuell generiert werden muss, ist hier ggf. etwas zu generieren? +Ggf. eine eigenes Beschreibungssprache? + + diff --git a/fx/src/main/java/de/neitzel/fx/component/controls/Binding.java b/fx/src/main/java/de/neitzel/fx/component/controls/Binding.java new file mode 100644 index 0000000..f4dc831 --- /dev/null +++ b/fx/src/main/java/de/neitzel/fx/component/controls/Binding.java @@ -0,0 +1,67 @@ +package de.neitzel.fx.component.controls; + +import de.neitzel.fx.component.model.BindingData; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.scene.layout.Region; + +/** + * The BindingControl class represents a UI control that manages a list + * of {@link BindingData} objects. It extends the {@link Region} class and + * provides functionality to bind and monitor connections between source + * and target properties. + * + * The primary purpose of this control is to maintain an observable list + * of bindings, allowing developers to track or adjust the linked properties + * dynamically. + * + * The internal list of bindings is implemented as an {@link ObservableList}, + * allowing property change notifications to be easily monitored for UI + * updates or other reactive behaviors. + * + * This class serves as an organizational component and does not provide + * any user interaction by default. + */ +public class Binding extends Region { + + /** + * Represents an observable list of {@link BindingData} objects contained within the + * {@link Binding} instance. This list is utilized to manage and monitor + * the bindings between source and target properties dynamically. + * + * The list is implemented as an {@link ObservableList}, allowing changes in the + * collection to be observed and reacted to, such as triggering UI updates or + * responding to binding modifications. + * + * This field is initialized as an empty list using {@link FXCollections#observableArrayList()}. + * It is declared as final to ensure its reference cannot be changed, while the + * contents of the list remain mutable. + */ + private final ObservableList bindings = FXCollections.observableArrayList(); + + /** + * Retrieves the observable list of {@code Binding} objects associated with this control. + * The returned list allows monitoring and management of the bindings maintained + * by the {@code BindingControl}. + * + * @return an {@code ObservableList} containing the bindings managed by this control + */ + public ObservableList getBindings() { + return bindings; + } + + /** + * Constructs a new instance of the BindingControl class. + * + * This default constructor initializes the BindingControl without + * any pre-configured bindings. The instance will contain an empty + * {@link ObservableList} of {@link BindingData} objects, which can later + * be populated as needed. + * + * The constructor does not perform additional setup or initialization, + * allowing the class to be extended or customized as necessary. + */ + public Binding() { + // Absichtlich leer – wird später "ausgewertet" + } +} \ No newline at end of file diff --git a/fx/src/main/java/de/neitzel/fx/component/controls/FxmlComponent.java b/fx/src/main/java/de/neitzel/fx/component/controls/FxmlComponent.java new file mode 100644 index 0000000..a871db4 --- /dev/null +++ b/fx/src/main/java/de/neitzel/fx/component/controls/FxmlComponent.java @@ -0,0 +1,90 @@ +package de.neitzel.fx.component.controls; + +import de.neitzel.fx.component.ComponentLoader; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.scene.Node; +import javafx.scene.Parent; +import javafx.scene.layout.StackPane; + +import java.io.IOException; +import java.util.Arrays; + +public class FxmlComponent extends StackPane { + + private final StringProperty fxml = new SimpleStringProperty(); + private final StringProperty direction = new SimpleStringProperty("unidirectional"); + private final ObjectProperty data = new SimpleObjectProperty<>(); + + public StringProperty fxmlProperty() { return fxml; } + public String getFxml() { return fxml.get(); } + public void setFxml(String fxml) { this.fxml.set(fxml); } + + public StringProperty directionProperty() { return direction; } + public String getDirection() { return direction.get(); } + public void setDirection(String direction) { this.direction.set(direction); } + + public ObjectProperty dataProperty() { return data; } + public Object getData() { return data.get(); } + public void setData(Object data) { this.data.set(data); } + + public FxmlComponent() { + fxml.addListener((obs, oldVal, newVal) -> load()); + data.addListener((obs, oldVal, newVal) -> injectData()); + } + + private void load() { + if (getFxml() == null || getFxml().isBlank()) return; + try { + ComponentLoader loader = new ComponentLoader(); + // Option: ControllerFactory verwenden, wenn nötig + Parent content = loader.load(getClass().getResource(getFxml())); + + getChildren().setAll(content); + + Object controller = loader.getController(); + if (controller != null && getData() != null) { + injectDataToController(controller, getData()); + } + + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void injectData() { + if (!getChildren().isEmpty() && getData() != null) { + Object controller = getControllerFromChild(getChildren().get(0)); + if (controller != null) { + injectDataToController(controller, getData()); + } + } + } + + private void injectDataToController(Object controller, Object dataObject) { + // Daten-Objekt per Reflection zuweisen + // Beispiel: Controller hat `setData(User data)` + Arrays.stream(controller.getClass().getMethods()) + .filter(m -> m.getName().equals("setData") && m.getParameterCount() == 1) + .findFirst() + .ifPresent(method -> { + try { + method.invoke(controller, dataObject); + } catch (Exception e) { + e.printStackTrace(); + } + }); + + // Optional: automatisch Binding ausführen (s. u.) + } + + private Object getControllerFromChild(Node node) { + if (node.getProperties().containsKey("fx:controller")) { + return node.getProperties().get("fx:controller"); + } + return null; + } +} + diff --git a/fx/src/main/java/de/neitzel/fx/component/model/BindingData.java b/fx/src/main/java/de/neitzel/fx/component/model/BindingData.java new file mode 100644 index 0000000..6c7ba64 --- /dev/null +++ b/fx/src/main/java/de/neitzel/fx/component/model/BindingData.java @@ -0,0 +1,82 @@ +package de.neitzel.fx.component.model; + +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; + +/** + * The Binding class represents a connection between a source and a target, + * with an associated direction. It is typically used to define a binding + * relationship that determines how data flows between these two entities. + * + * The class provides three properties: + * - direction: Represents the type of the binding. Defaults to "unidirectional". + * - source: Represents the source of the binding. + * - target: Represents the target of the binding. + * + * It uses JavaFX property types, allowing these properties to be observed + * for changes. + */ +public class BindingData { + /** + * Represents the direction of the binding in the {@code Binding} class. + * It determines whether the binding is unidirectional or bidirectional. + * The default value is "unidirectional". + * + * This property is observed for changes, enabling dynamic updates + * within the JavaFX property system. + */ + private StringProperty direction = new SimpleStringProperty("unidirectional"); + /** + * Represents the source of the binding. This property holds a string value + * that specifies the originating object or identifier in the binding connection. + * It can be observed for changes, allowing updates to the binding relationship + * when the source value is modified. + */ + private StringProperty source = new SimpleStringProperty(); + /** + * Represents the target of the binding in the Binding class. + * This property holds the target value, which can be observed for changes. + */ + private StringProperty target = new SimpleStringProperty(); + + /** + * Gets the current direction of the binding. + * The direction determines how data flows between + * the source and the target, and typically defaults to "unidirectional". + * + * @return the current direction of the binding + */ + public String getDirection() { return direction.get(); } + /** + * Sets the direction of the binding. + * + * @param dir the new direction to set for the binding + */ + public void setDirection(String dir) { direction.set(dir); } + + /** + * Gets the current source value of the binding. + * + * @return the source value as a String. + */ + public String getSource() { return source.get(); } + /** + * Sets the value of the source property for this binding. + * + * @param source the new source value to be set + */ + public void setSource(String source) { this.source.set(source); } + + /** + * Retrieves the current value of the target property. + * + * @return the value of the target property as a String. + */ + public String getTarget() { return target.get(); } + /** + * Sets the target property of the binding. + * + * @param target the new value to set for the target property + */ + public void setTarget(String target) { this.target.set(target); } +} \ No newline at end of file -- 2.47.1 From 5aa75be6ba406013c11863abc7e702666d1313a7 Mon Sep 17 00:00:00 2001 From: Konrad Neitzel Date: Tue, 1 Jul 2025 15:38:07 +0200 Subject: [PATCH 3/8] Added FileUtils / TempDirectory from EmailTool. Moved FileUtils to io package. --- .../de/neitzel/core/config/Configuration.java | 68 ++--- .../core/io/ConvertedEncodingFileReader.java | 66 ++--- .../neitzel/core/{util => io}/FileUtils.java | 192 ++++++++----- .../de/neitzel/core/io/TempDirectory.java | 76 ++++++ fx/ideas.md | 86 +++++- .../neitzel/fx/component/ComponentLoader.java | 258 +++++++++--------- .../fx/component/controls/Binding.java | 40 +-- .../fx/component/controls/FxmlComponent.java | 69 +++-- .../fx/component/model/BindingData.java | 1 + 9 files changed, 550 insertions(+), 306 deletions(-) rename core/src/main/java/de/neitzel/core/{util => io}/FileUtils.java (78%) create mode 100644 core/src/main/java/de/neitzel/core/io/TempDirectory.java diff --git a/core/src/main/java/de/neitzel/core/config/Configuration.java b/core/src/main/java/de/neitzel/core/config/Configuration.java index 94d9f3f..010b8e3 100644 --- a/core/src/main/java/de/neitzel/core/config/Configuration.java +++ b/core/src/main/java/de/neitzel/core/config/Configuration.java @@ -1,6 +1,6 @@ package de.neitzel.core.config; -import de.neitzel.core.util.FileUtils; +import de.neitzel.core.io.FileUtils; import de.neitzel.core.util.Strings; import lombok.extern.slf4j.Slf4j; @@ -28,7 +28,7 @@ public class Configuration { * A {@link Properties} object that stores a set of key-value pairs. * This variable can be used to manage configuration settings or other * collections of properties within the application. - * + *

* It provides methods to load, retrieve, and modify properties * as necessary for the application's requirements. */ @@ -56,20 +56,20 @@ public class Configuration { * Retrieves a boolean property value associated with the specified key. If the key does not exist in the properties, * the provided default value is returned. The method also supports interpreting specific string values as true. * - * @param key the key used to retrieve the boolean property + * @param key the key used to retrieve the boolean property * @param defaultValue the default value returned if the key is not found in the properties * @return the boolean value associated with the key, or the defaultValue if the key does not exist */ protected boolean getBooleanProperty(final String key, final boolean defaultValue) { if (!properties.containsKey(key)) return defaultValue; - return getStringProperty(key, defaultValue ? "ja": "nein").equalsIgnoreCase("ja") || properties.getProperty(key).equalsIgnoreCase("true"); + return getStringProperty(key, defaultValue ? "ja" : "nein").equalsIgnoreCase("ja") || properties.getProperty(key).equalsIgnoreCase("true"); } /** * Retrieves the value of the specified property as a trimmed string. * If the property is not found, the default value is returned. * - * @param key the key of the property to retrieve + * @param key the key of the property to retrieve * @param defaultValue the default value to return if the property is not found * @return the trimmed string value of the property, or the default value if the property is not found */ @@ -82,34 +82,22 @@ public class Configuration { * Retrieves a string property value associated with the specified key, applies * environment variable expansion on the value, and returns the processed result. * - * @param key the key identifying the property to retrieve. + * @param key the key identifying the property to retrieve. * @param defaultValue the default value to use if the property is not found. * @return the processed property value with expanded environment variables, or - * the defaultValue if the property is not found. + * the defaultValue if the property is not found. */ protected String getStringPropertyWithEnv(final String key, final String defaultValue) { String result = getStringProperty(key, defaultValue); return Strings.expandEnvironmentVariables(result); } - /** - * Retrieves the value of a string property associated with the specified key, - * removes any surrounding quotes from the value, and returns the resultant string. - * - * @param key the key associated with the desired property - * @param defaultValue the default value to return if the property is not found or is null - * @return the string property without surrounding quotes, or the defaultValue if the property is not found - */ - protected String getStringPropertyWithoutQuotes(final String key, final String defaultValue) { - return Strings.removeQuotes(getStringProperty(key, defaultValue)); - } - /** * Retrieves the string value of a configuration property identified by the given key, * removes surrounding quotes if present, and expands any environment variables found * within the string. If the property is not found, a default value is used. * - * @param key the key identifying the configuration property + * @param key the key identifying the configuration property * @param defaultValue the default value to use if the property is not found * @return the processed string property with quotes removed and environment variables expanded */ @@ -118,16 +106,28 @@ public class Configuration { return Strings.expandEnvironmentVariables(result); } + /** + * Retrieves the value of a string property associated with the specified key, + * removes any surrounding quotes from the value, and returns the resultant string. + * + * @param key the key associated with the desired property + * @param defaultValue the default value to return if the property is not found or is null + * @return the string property without surrounding quotes, or the defaultValue if the property is not found + */ + protected String getStringPropertyWithoutQuotes(final String key, final String defaultValue) { + return Strings.removeQuotes(getStringProperty(key, defaultValue)); + } + /** * Retrieves the integer value for the specified property key. If the key does * not exist in the properties or the value is null/empty, the provided default * value is returned. * - * @param key the property key to retrieve the value for + * @param key the property key to retrieve the value for * @param defaultValue the default value to return if the key is not present * or the value is null/empty * @return the integer value associated with the key, or the defaultValue if - * the key does not exist or its value is null/empty + * the key does not exist or its value is null/empty */ protected Integer getIntegerProperty(final String key, final Integer defaultValue) { if (!properties.containsKey(key)) return defaultValue; @@ -139,14 +139,14 @@ public class Configuration { * Sets an integer property in the properties object. If the provided value is null, * an empty string will be stored as the property's value. * - * @param key the key under which the property will be stored + * @param key the key under which the property will be stored * @param value the integer value to be stored; if null, an empty string will be used */ protected void setIntegerProperty(final String key, final Integer value) { if (value == null) { properties.setProperty(key, ""); } else { - properties.setProperty(key, ""+value); + properties.setProperty(key, "" + value); } } @@ -154,11 +154,11 @@ public class Configuration { * Retrieves a LocalDate value from the properties based on the provided key. * If the key does not exist or the value is invalid, a default value is returned. * - * @param key the key to look up the property in the properties map + * @param key the key to look up the property in the properties map * @param defaultValue the default LocalDate value to return if the key is not found * @param formatString the format string to parse the LocalDate value * @return the LocalDate value from the properties if available and valid, - * otherwise the defaultValue + * otherwise the defaultValue */ protected LocalDate getLocalDateProperty(final String key, final LocalDate defaultValue, final String formatString) { if (!properties.containsKey(key)) return defaultValue; @@ -172,8 +172,8 @@ public class Configuration { * Sets a property with the given key and a formatted LocalDate value. * If the provided value is null, the property will be set to an empty string. * - * @param key the key of the property to set - * @param value the LocalDate value to format and set as the property value + * @param key the key of the property to set + * @param value the LocalDate value to format and set as the property value * @param formatString the pattern string used to format the LocalDate value */ protected void setLocalDateProperty(final String key, final LocalDate value, final String formatString) { @@ -188,7 +188,7 @@ public class Configuration { * Sets a property with the specified key to the given value. If the value is null, * it defaults to an empty string. Logs the operation and updates the property. * - * @param key the key of the property to be set + * @param key the key of the property to be set * @param value the value to be associated with the specified key; defaults to an empty string if null */ public void setProperty(final String key, final String value) { @@ -211,9 +211,9 @@ public class Configuration { * specified location, it attempts to find the file alongside the JAR file of the application. * Reads the configuration with the provided encoding and an option to accept UTF-8 encoding. * - * @param fileName the name of the configuration file to be loaded - * @param encoding the encoding format to be used while reading the configuration file - * @param acceptUTF8 a boolean flag indicating whether to accept UTF-8 encoding + * @param fileName the name of the configuration file to be loaded + * @param encoding the encoding format to be used while reading the configuration file + * @param acceptUTF8 a boolean flag indicating whether to accept UTF-8 encoding */ public void load(final String fileName, final String encoding, final boolean acceptUTF8) { log.info("Reading Config: " + fileName + " with encoding: " + encoding + "accepting UTF-8: " + acceptUTF8); @@ -251,7 +251,7 @@ public class Configuration { * @param config the Configuration object whose properties will be merged into this instance */ public void merge(final Configuration config) { - for(Map.Entry entry: config.properties.entrySet()) { + for (Map.Entry entry : config.properties.entrySet()) { properties.put(entry.getKey(), entry.getValue()); } } @@ -261,7 +261,7 @@ public class Configuration { * * @param key the key to be removed from the properties map */ - public void remove(final String key){ + public void remove(final String key) { if (properties.containsKey(key)) properties.remove(key); } } diff --git a/core/src/main/java/de/neitzel/core/io/ConvertedEncodingFileReader.java b/core/src/main/java/de/neitzel/core/io/ConvertedEncodingFileReader.java index aa37570..ce6205c 100644 --- a/core/src/main/java/de/neitzel/core/io/ConvertedEncodingFileReader.java +++ b/core/src/main/java/de/neitzel/core/io/ConvertedEncodingFileReader.java @@ -1,6 +1,5 @@ package de.neitzel.core.io; -import de.neitzel.core.util.FileUtils; import lombok.extern.slf4j.Slf4j; import java.io.*; @@ -12,7 +11,7 @@ import java.nio.charset.IllegalCharsetNameException; * for handling file encoding conversion transparently. If a file is detected to be in UTF-8 encoding, * this class converts it to the specified target encoding using a temporary file, then opens the reader * with the converted encoding. If the file is already in the target encoding, it opens the reader directly. - * + *

* This class is useful for applications needing to process text files in specific encodings and ensures * encoding compatibility. */ @@ -25,47 +24,19 @@ public class ConvertedEncodingFileReader extends InputStreamReader { * This encoding is primarily used to determine whether a file needs conversion * to the target format or can be read directly in its existing format. * The default value is set to "ISO-8859-15". - * + *

* Modifying this variable requires careful consideration, as it affects * the behavior of methods that rely on encoding validation, particularly * in the process of detecting UTF-8 files or converting them during file reading. */ private static String checkEncoding = "ISO-8859-15"; - /** - * Sets the encoding that will be used to check the file encoding for compatibility. - * Throws an exception if the specified encoding is not valid or supported. - * - * @param encoding the name of the character encoding to set as the check encoding; - * it must be a valid and supported Charset. - * @throws IllegalCharsetNameException if the specified encoding is not valid or supported. - */ - private static void setCheckEncoding(final String encoding) { - if (Charset.forName(encoding) != null) throw new IllegalCharsetNameException("Encoding " + encoding + " is not supported!"); - - checkEncoding = encoding; - } - - /** - * Constructs a ConvertedEncodingFileReader for a specified file and target encoding format. - * The class reads the provided file and ensures that its content is handled in the target encoding. - * If the file is not already in the target encoding, it converts the file's encoding - * transparently using a temporary file before reading it. - * - * @param file The file to be read. Must exist and be accessible. - * @param targetFormat The target character encoding format to which the file content should be converted. - * @throws IOException If the file does not exist, is inaccessible, or an error occurs during the encoding conversion process. - */ - public ConvertedEncodingFileReader(final File file, final String targetFormat) throws IOException { - super(createTargetFormatInputFileStream(file, targetFormat), targetFormat); - } - /** * Constructs a ConvertedEncodingFileReader for reading a file with encoding conversion support. * This constructor takes the file path as a string and ensures the file's encoding is either * converted to the specified target format or read directly if it matches the target format. * - * @param filename the path to the file to be read + * @param filename the path to the file to be read * @param targetFormat the target encoding format to use for reading the file * @throws IOException if an I/O error occurs while accessing or reading the specified file */ @@ -73,13 +44,27 @@ public class ConvertedEncodingFileReader extends InputStreamReader { this(new File(filename), targetFormat); } + /** + * Constructs a ConvertedEncodingFileReader for a specified file and target encoding format. + * The class reads the provided file and ensures that its content is handled in the target encoding. + * If the file is not already in the target encoding, it converts the file's encoding + * transparently using a temporary file before reading it. + * + * @param file The file to be read. Must exist and be accessible. + * @param targetFormat The target character encoding format to which the file content should be converted. + * @throws IOException If the file does not exist, is inaccessible, or an error occurs during the encoding conversion process. + */ + public ConvertedEncodingFileReader(final File file, final String targetFormat) throws IOException { + super(createTargetFormatInputFileStream(file, targetFormat), targetFormat); + } + /** * Creates an input file stream for a given file, converting its encoding if necessary. * If the file is not in UTF-8 encoding, a direct {@link FileInputStream} is returned for the file. * If the file is in UTF-8 encoding, it is converted to the specified target format using a temporary file, * and then an input stream for the temporary file is returned. * - * @param file the file for which the input stream is to be created + * @param file the file for which the input stream is to be created * @param targetFormat the desired target encoding format * @return a {@link FileInputStream} for the file or a temporary file with converted encoding * @throws IOException if the file does not exist or an error occurs during file operations @@ -100,4 +85,19 @@ public class ConvertedEncodingFileReader extends InputStreamReader { return new FileInputStream(tempFile); } } + + /** + * Sets the encoding that will be used to check the file encoding for compatibility. + * Throws an exception if the specified encoding is not valid or supported. + * + * @param encoding the name of the character encoding to set as the check encoding; + * it must be a valid and supported Charset. + * @throws IllegalCharsetNameException if the specified encoding is not valid or supported. + */ + private static void setCheckEncoding(final String encoding) { + if (Charset.forName(encoding) != null) + throw new IllegalCharsetNameException("Encoding " + encoding + " is not supported!"); + + checkEncoding = encoding; + } } diff --git a/core/src/main/java/de/neitzel/core/util/FileUtils.java b/core/src/main/java/de/neitzel/core/io/FileUtils.java similarity index 78% rename from core/src/main/java/de/neitzel/core/util/FileUtils.java rename to core/src/main/java/de/neitzel/core/io/FileUtils.java index 6bb3219..5d99475 100644 --- a/core/src/main/java/de/neitzel/core/util/FileUtils.java +++ b/core/src/main/java/de/neitzel/core/io/FileUtils.java @@ -1,31 +1,21 @@ -package de.neitzel.core.util; +package de.neitzel.core.io; +import de.neitzel.core.util.ArrayUtils; import lombok.extern.slf4j.Slf4j; import java.io.*; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.text.SimpleDateFormat; import java.util.stream.Collectors; /** - * Utility class for handling file operations, such as encoding checks, content reading/writing, - * path manipulations, and file conversions. + * A utility class for file-related operations. This class provides functionalities + * for handling files and directories in an efficient manner. */ @Slf4j public class FileUtils { - /** - * Private constructor to prevent instantiation of the utility class. - * This utility class is not meant to be instantiated, as it only provides - * static utility methods for array-related operations. - * - * @throws UnsupportedOperationException always, to indicate that this class - * should not be instantiated. - */ - private FileUtils() { - throw new UnsupportedOperationException("Utility class"); - } - /** * Defines a standardized timestamp format for debugging purposes, specifically used for naming * or identifying files with precise timestamps. The format is "yyyy-MM-dd_HH_mm_ss_SSS", which @@ -37,14 +27,14 @@ public class FileUtils { * - Minutes in two digits (mm) * - Seconds in two digits (ss) * - Milliseconds in three digits (SSS) - * + *

* This ensures timestamps are sortable and easily identifiable. */ public static final SimpleDateFormat DEBUG_FILE_TIMESTAMP_FORMAT = new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss_SSS"); /** * Default encoding used for string checks and validations in the application. - * + *

* This constant represents the `ISO-8859-15` encoding, which is a standardized * character set encoding, commonly used in contexts where backward compatibility * with `ISO-8859-1` is required, but with support for certain additional characters, @@ -54,17 +44,40 @@ public class FileUtils { /** * Specifies the default buffer size used for data processing operations. - * + *

* This constant represents the size of the buffer in bytes, set to 1024, * and is typically utilized in input/output operations to optimize performance * by reducing the number of read/write calls. */ public static final int BUFFER_SIZE = 1024; + /** + * Private constructor to prevent instantiation of the utility class. + * This utility class is not meant to be instantiated, as it only provides + * static utility methods for array-related operations. + * + * @throws UnsupportedOperationException always, to indicate that this class + * should not be instantiated. + */ + private FileUtils() { + throw new UnsupportedOperationException("Utility class"); + } + + /** + * Determines if the content of the given file is encoded in UTF-8. + * + * @param file The file to check for UTF-8 encoding. Must not be null. + * @return true if the file content is in UTF-8 encoding; false otherwise. + * @throws IOException If an I/O error occurs while reading the file. + */ + public static boolean isUTF8(final File file) throws IOException { + return isUTF8(file, DEFAULT_CHECK_ENCODING); + } + /** * Determines whether the given file is encoded in UTF-8. * - * @param file The file to be checked for UTF-8 encoding. + * @param file The file to be checked for UTF-8 encoding. * @param checkEncoding The character encoding to use while checking the file content. * @return true if the file is determined to be encoded in UTF-8; false otherwise. * @throws IOException If an I/O error occurs while reading the file. @@ -82,7 +95,7 @@ public class FileUtils { if ( (ArrayUtils.contains(buffer, (char) 0x00C2)) // Part of UTF-8 Characters 0xC2 0xZZ - || (ArrayUtils.contains(buffer, (char) 0x00C3))) { // Part of UTF-8 Characters 0xC3 0xZZ + || (ArrayUtils.contains(buffer, (char) 0x00C3))) { // Part of UTF-8 Characters 0xC3 0xZZ return true; } @@ -97,7 +110,7 @@ public class FileUtils { /** * Checks if the provided file starts with a UTF-8 Byte Order Mark (BOM). - * + *

* This method reads the first character of the file using a reader that assumes * UTF-8 encoding and checks if it matches the Unicode Byte Order Mark (U+FEFF). * @@ -114,26 +127,15 @@ public class FileUtils { } } - /** - * Determines if the content of the given file is encoded in UTF-8. - * - * @param file The file to check for UTF-8 encoding. Must not be null. - * @return true if the file content is in UTF-8 encoding; false otherwise. - * @throws IOException If an I/O error occurs while reading the file. - */ - public static boolean isUTF8(final File file) throws IOException { - return isUTF8(file, DEFAULT_CHECK_ENCODING); - } - /** * Converts the content of a text file from one character encoding format to another. - * + *

* This method reads the input text file using the specified source encoding and writes * the content to the output text file in the specified target encoding. * - * @param inFile The input text file to be converted. Must not be null. + * @param inFile The input text file to be converted. Must not be null. * @param sourceFormat The character encoding of the input file. Must not be null or empty. - * @param outFile The output text file to write the converted content to. Must not be null. + * @param outFile The output text file to write the converted content to. Must not be null. * @param targetFormat The character encoding to be used for the output file. Must not be null or empty. * @throws IOException If an I/O error occurs during reading or writing. */ @@ -167,25 +169,12 @@ public class FileUtils { } } - /** - * Creates a universal file reader for the specified file name. - * This method initializes and returns an InputStreamReader to read - * the content of the given file. - * - * @param filename The name or path of the file to be read. - * @return An InputStreamReader for reading the specified file. - * @throws IOException If an I/O error occurs while creating the file reader. - */ - public static InputStreamReader createUniversalFileReader(final String filename) throws IOException { - return createUniversalFileReader(new File(filename)); - } - /** * Creates a universal file reader for the specified file and format. * The method resolves the file using its name and the expected format, * returning an InputStreamReader for reading the file contents. * - * @param filename the name of the file to be read. + * @param filename the name of the file to be read. * @param expectedFormat the format expected for the file content. * @return an InputStreamReader for the specified file and format. * @throws IOException if an I/O error occurs while opening or reading the file. @@ -194,25 +183,14 @@ public class FileUtils { return createUniversalFileReader(new File(filename), expectedFormat); } - /** - * Creates a universal file reader for the specified file using the default encoding and configuration. - * - * @param file The file to be read. Must not be null. - * @return An InputStreamReader configured to read the specified file. - * @throws IOException If an I/O error occurs while creating the reader. - */ - public static InputStreamReader createUniversalFileReader(final File file) throws IOException { - return createUniversalFileReader(file, DEFAULT_CHECK_ENCODING, true); - } - /** * Creates a universal file reader for the specified file with an expected format. * This method wraps the given file in an InputStreamReader for consistent character stream manipulation. * - * @param file The file to be read. Must not be null. + * @param file The file to be read. Must not be null. * @param expectedFormat The expected format of the file (e.g., encoding). Must not be null. * @return An InputStreamReader for the specified file, allowing the caller to read the file - * with the desired format applied. + * with the desired format applied. * @throws IOException If an I/O error occurs during the creation of the reader. */ public static InputStreamReader createUniversalFileReader(final File file, final String expectedFormat) throws IOException { @@ -223,9 +201,9 @@ public class FileUtils { * Creates an InputStreamReader for reading a file, considering the specified encoding format * and whether UTF-8 should be accepted. Handles potential BOM for UTF-8 encoded files. * - * @param file The file to be read. + * @param file The file to be read. * @param expectedFormat The expected encoding format of the file. - * @param acceptUTF8 Indicates whether UTF-8 encoding should be accepted if detected. + * @param acceptUTF8 Indicates whether UTF-8 encoding should be accepted if detected. * @return An InputStreamReader for the specified file and encoding. * @throws IOException If there is an error accessing the file or reading its content. */ @@ -239,14 +217,14 @@ public class FileUtils { InputStreamReader result = new InputStreamReader(new FileInputStream(file), encoding); if (skipBOM) { int BOM = result.read(); - if (BOM != 0xFEFF) log.error ("Skipping BOM but value not 0xFEFF!"); + if (BOM != 0xFEFF) log.error("Skipping BOM but value not 0xFEFF!"); } return result; } /** * Retrieves the parent directory of the given file or directory path. - * + *

* If the given path does not have a parent directory, it defaults to returning the * current directory represented by ".". * @@ -282,10 +260,34 @@ public class FileUtils { } } + /** + * Creates a universal file reader for the specified file name. + * This method initializes and returns an InputStreamReader to read + * the content of the given file. + * + * @param filename The name or path of the file to be read. + * @return An InputStreamReader for reading the specified file. + * @throws IOException If an I/O error occurs while creating the file reader. + */ + public static InputStreamReader createUniversalFileReader(final String filename) throws IOException { + return createUniversalFileReader(new File(filename)); + } + + /** + * Creates a universal file reader for the specified file using the default encoding and configuration. + * + * @param file The file to be read. Must not be null. + * @return An InputStreamReader configured to read the specified file. + * @throws IOException If an I/O error occurs while creating the reader. + */ + public static InputStreamReader createUniversalFileReader(final File file) throws IOException { + return createUniversalFileReader(file, DEFAULT_CHECK_ENCODING, true); + } + /** * Writes the given content to the specified file path. If the file already exists, it will be overwritten. * - * @param path The path of the file to write to. Must not be null and must be writable. + * @param path The path of the file to write to. Must not be null and must be writable. * @param content The content to be written to the file. Must not be null. * @throws IOException If an I/O error occurs during writing to the file. */ @@ -294,4 +296,60 @@ public class FileUtils { writer.write(content); } } + + /** + * Deletes the specified file or directory. If the target is a directory, all its contents, + * including subdirectories and files, will be deleted recursively. + * If the target file or directory does not exist, the method immediately returns {@code true}. + * + * @param targetFile the {@code Path} of the file or directory to be deleted + * @return {@code true} if the target file or directory was successfully deleted, + * or if it does not exist; {@code false} if an error occurred during deletion + */ + public static boolean remove(Path targetFile) { + if (!Files.exists(targetFile)) { + return true; + } + + if (Files.isDirectory(targetFile)) { + return removeDirectory(targetFile); + } + + return targetFile.toFile().delete(); + } + + /** + * Deletes the specified directory and all its contents, including subdirectories and files. + * The method performs a recursive deletion, starting with the deepest entries in the directory tree. + * If the directory does not exist, the method immediately returns true. + * + * @param targetDir the {@code Path} of the directory to be deleted + * @return {@code true} if the directory and all its contents were successfully deleted + * or if the directory does not exist; {@code false} if an error occurred during deletion + */ + public static boolean removeDirectory(Path targetDir) { + if (!Files.exists(targetDir)) { + return true; + } + + if (!Files.isDirectory(targetDir)) { + return false; + } + + try { + Files.walk(targetDir) + .sorted((a, b) -> b.compareTo(a)) + .forEach(path -> { + try { + Files.deleteIfExists(path); + } catch (Exception ignored) { + } + }); + } catch (IOException ignored) { + return false; + } + + return true; + } + } diff --git a/core/src/main/java/de/neitzel/core/io/TempDirectory.java b/core/src/main/java/de/neitzel/core/io/TempDirectory.java new file mode 100644 index 0000000..f7ea1ed --- /dev/null +++ b/core/src/main/java/de/neitzel/core/io/TempDirectory.java @@ -0,0 +1,76 @@ +package de.neitzel.core.io; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Comparator; +import java.util.stream.Stream; + +/** + * A utility class for creating and managing a temporary directory. + * Instances of this class create a unique temporary directory on the filesystem + * that can safely be used during the runtime of a program. + *

+ * The directory is automatically cleaned up when the instance is closed. + */ +public class TempDirectory implements AutoCloseable { + + /** + * The filesystem path representing the temporary directory managed by this instance. + * This path is initialized when the TempDirectory object is created and points + * to a unique, newly created directory. + *

+ * The directory can be used to safely store temporary runtime files. It is automatically + * deleted along with its content when the associated TempDirectory object is closed. + */ + private final Path directory; + + /** + * Creates a temporary directory with a unique name on the filesystem. + * The directory will have a prefix specified by the user and is intended + * to serve as a temporary workspace during the runtime of the program. + * + * @param prefix the prefix to be used for the name of the temporary directory + * @throws IOException if an I/O error occurs when creating the directory + */ + public TempDirectory(String prefix) throws IOException { + this.directory = Files.createTempDirectory(prefix); + } + + /** + * Retrieves the path of the temporary directory associated with this instance. + * + * @return the {@code Path} of the temporary directory + */ + public Path getDirectory() { + return directory; + } + + /** + * Closes the temporary directory by cleaning up its contents and deleting the directory itself. + *

+ * This method ensures that all files and subdirectories within the temporary directory are + * deleted in a reverse order, starting from the deepest leaf in the directory tree. If + * the directory does not exist, the method will not perform any actions. + *

+ * If an error occurs while deleting any file or directory, a RuntimeException is thrown + * with the details of the failure. + * + * @throws IOException if an I/O error occurs while accessing the directory or its contents. + */ + @Override + public void close() throws IOException { + if (Files.exists(directory)) { + try (Stream walk = Files.walk(directory)) { + walk.sorted(Comparator.reverseOrder()) + .forEach(path -> { + try { + Files.delete(path); + } catch (IOException e) { + throw new RuntimeException("Failed to delete: " + path, e); + } + }); + } + } + } +} diff --git a/fx/ideas.md b/fx/ideas.md index 8c180d5..8fa6cf0 100644 --- a/fx/ideas.md +++ b/fx/ideas.md @@ -1,15 +1,99 @@ +# TODO + +- SimpleListProperty auch nutzen bei Collections! + # Ideen # Bindings + Bindngs kommen über ein spezielles Binding Control, das dann notwendige Bindings beinhaltet. -Da kann dann auch eine eigene Logik zur Erkennung des Bindings erfolgen oder zusätziche Informationen bezüglich notwendiger Elemente in dem ViewModel +Da kann dann auch eine eigene Logik zur Erkennung des Bindings erfolgen oder zusätziche Informationen bezüglich +notwendiger Elemente in dem ViewModel + +## Bidirektional Converter für Bindings + +```Java +StringConverter converter = new StringConverter<>() { + private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault()); + + @Override + public String toString(Instant instant) { + return instant == null ? "" : formatter.format(instant); + } + + @Override + public Instant fromString(String string) { + if (string == null || string.isBlank()) return null; + try { + LocalDateTime dateTime = LocalDateTime.parse(string, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + return dateTime.atZone(ZoneId.systemDefault()).toInstant(); + } catch (DateTimeParseException e) { + // Optional: Fehlermeldung anzeigen + return null; + } + } +}; + +// Binding einrichten: +Bindings. + +bindBidirectional(textField.textProperty(),instantProperty,converter); +``` + +Overloads von bindBidirectional +bindBidirectional(Property, Property, Format) +bindBidirectional(Property, Property, StringConverter) +bindBidirectional(Property, Property) + +## Unidirektional mit Bindings.createStringBinding() + +```Java +DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault()); + +textField. + +textProperty(). + +bind(Bindings.createStringBinding( + () ->{ + +Instant instant = instantProperty.get(); + return instant ==null?"":formatter. + +format(instant); + }, +instantProperty +)); +``` + +Bindings: + +- BooleanBinding +- DoubleBinding +- FloatBinding +- IntegerBinding +- LongBinding +- StringBinding +- ObjectBinding +- NumberBinding + +Bindings haben Methoden, die dann weitere Bindings erzeugen. +==> Parameter der Methode: Property, Observable und einer Methode, die ein Binding erstellt und das ViewModel, das +dann genutzt werden kann, um weitere Properties zu holen ==> Erzeugung von neuen Properties. + +Diese BindingCreators haben Namen, PropertyTyp und ein BindingType. # FXMLComponent + Dient dem Laden einer Komponente und bekommt dazu das fxml, die Daten und ggf. auch eine ModelView. # ModelView generieren + Damit eine ModelView nicht ständig manuell generiert werden muss, ist hier ggf. etwas zu generieren? Ggf. eine eigenes Beschreibungssprache? +# Aufbau einer Validierung +- gehört in das ViewModel +- \ No newline at end of file diff --git a/fx/src/main/java/de/neitzel/fx/component/ComponentLoader.java b/fx/src/main/java/de/neitzel/fx/component/ComponentLoader.java index 84f8bc2..9859156 100644 --- a/fx/src/main/java/de/neitzel/fx/component/ComponentLoader.java +++ b/fx/src/main/java/de/neitzel/fx/component/ComponentLoader.java @@ -1,12 +1,20 @@ package de.neitzel.fx.component; +import de.neitzel.fx.component.controls.Binding; +import de.neitzel.fx.component.controls.FxmlComponent; +import de.neitzel.fx.component.model.BindingData; import javafx.beans.property.Property; +import javafx.beans.value.ObservableValue; import javafx.fxml.FXMLLoader; +import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.layout.Pane; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; -import java.io.File; import java.io.IOException; +import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; @@ -16,13 +24,35 @@ import java.util.Map; /** * ComponentLoader is responsible for loading JavaFX FXML components and binding * them to automatically generated ViewModels based on simple POJO models. - *

- * It parses custom NFX attributes in FXML to bind UI elements to properties in the ViewModel, - * and supports recursive loading of subcomponents. */ +@Slf4j public class ComponentLoader { private Map> nfxBindingMap = new HashMap<>(); + @Getter + private Object controller; + + public Parent load(URL fxmlPath) { + return load(null, fxmlPath); + } + + public Parent load(String fxmlPath) { + return load(null, fxmlPath); + } + + public Parent load(Object model, URL fxmlPath) { + try { + AutoViewModel viewModel = new AutoViewModel<>(model); + FXMLLoader loader = new FXMLLoader(fxmlPath); + loader.setControllerFactory(type -> new ComponentController(viewModel)); + Parent root = loader.load(); + controller = loader.getController(); + return root; + } catch (IOException e) { + throw new RuntimeException("unable to load fxml: " + fxmlPath, e); + } + } + /** * Loads an FXML file and binds its elements to a generated ViewModel * based on the given POJO model. @@ -32,83 +62,116 @@ public class ComponentLoader { * @return the root JavaFX node loaded from FXML */ public Parent load(Object model, String fxmlPath) { + return load(model, getClass().getResource(fxmlPath)); + } + + public static T load(URL fxmlUrl, Object controller, String nothing) throws IOException { + FXMLLoader loader = new FXMLLoader(fxmlUrl); + loader.setController(controller); + T root = loader.load(); + + Map namespace = loader.getNamespace(); + + // Nach allen BindingControls suchen: + List bindingControls = collectAllNodes(root).stream() + .filter(n -> n instanceof Binding) + .map(n -> (Binding) n) + .toList(); + + for (Binding bc : bindingControls) { + evaluateBindings(bc.getBindings(), namespace); + } + + return root; + } + + private static void bindBidirectionalSafe(@NotNull Property source, Property target) { try { - AutoViewModel viewModel = new AutoViewModel<>(model); - String cleanedUri = preprocessNfxAttributes(fxmlPath); - FXMLLoader loader = new FXMLLoader(new URL(cleanedUri)); - loader.setControllerFactory(type -> new ComponentController(viewModel)); - Parent root = loader.load(); - processNfxBindings(root, viewModel, loader); - return root; - } catch (IOException e) { - throw new RuntimeException("unable to load fxml: " + fxmlPath, e); + Property targetCasted = (Property) target; + source.bindBidirectional(targetCasted); + } catch (ClassCastException e) { + log.error("⚠️ Typkonflikt beim Binding: %s ⇄ %s%n", source.getClass(), target.getClass(), e); } } - /** - * Processes all UI elements for NFX binding attributes and applies - * the appropriate bindings to the ViewModel. - * - * @param root the root node of the loaded FXML hierarchy - * @param viewModel the generated ViewModel to bind against - */ - private void processNfxBindings(Parent root, AutoViewModel viewModel, FXMLLoader loader) { - walkNodes(root, node -> { - var nfx = lookupNfxAttributes(node, loader); - String target = nfx.get("nfx:target"); - String direction = nfx.get("nfx:direction"); - String source = nfx.get("nfx:source"); - - if (target != null && direction != null) { - Property vmProp = viewModel.getProperty(target); - bindNodeToProperty(node, vmProp, direction); - } - - if (source != null) { - Object subModel = ((Property) viewModel.getProperty(target)).getValue(); - Parent subComponent = load(subModel, source); - if (node instanceof Pane pane) { - pane.getChildren().setAll(subComponent); - } - } - }); + private static void bindSafe(@NotNull Property source, Property target) { + try { + Property targetCasted = (Property) target; + source.bind(targetCasted); + } catch (ClassCastException e) { + log.error("⚠️ Typkonflikt beim Binding: %s ⇄ %s%n", source.getClass(), target.getClass(), e); + } } - /** - * Recursively walks all nodes in the scene graph starting from the root, - * applying the given consumer to each node. - * - * @param root the starting node - * @param consumer the consumer to apply to each node - */ - private void walkNodes(Parent root, java.util.function.Consumer consumer) { - consumer.accept(root); - if (root instanceof Pane pane) { - for (javafx.scene.Node child : pane.getChildren()) { - if (child instanceof Parent p) { - walkNodes(p, consumer); - } else { - consumer.accept(child); + private static void evaluateBindings(List bindings, Map namespace) { + for (var binding : bindings) { + try { + Object source = resolveExpression(binding.getSource(), namespace); + Object target = resolveExpression(binding.getTarget(), namespace); + + if (source instanceof Property && target instanceof Property) { + Property sourceProp = (Property) source; + Property targetProp = (Property) target; + + Class sourceType = getPropertyType(sourceProp); + Class targetType = getPropertyType(targetProp); + + boolean bindableForward = targetType.isAssignableFrom(sourceType); + boolean bindableBackward = sourceType.isAssignableFrom(targetType); + + switch (binding.getDirection().toLowerCase()) { + case "bidirectional": + if (bindableForward && bindableBackward) { + bindBidirectionalSafe(sourceProp, targetProp); + } else { + log.error("⚠️ Kann bidirektionales Binding nicht durchführen: Typen inkompatibel (%s ⇄ %s)%n", sourceType, targetType); + } + break; + case "unidirectional": + default: + if (bindableForward) { + bindSafe(sourceProp, targetProp); + } else { + log.error("⚠️ Kann unidirektionales Binding nicht durchführen: %s → %s nicht zuweisbar%n", sourceType, targetType); + } + break; + } } + } catch (Exception e) { + log.error("Fehler beim Binding: " + binding.getSource() + " → " + binding.getTarget(), e); } } } - /** - * Extracts custom NFX attributes from a node's properties map. - * These attributes are expected to be in the format "nfx:..." and hold string values. - * - * @param node the node to inspect - * @return a map of NFX attribute names to values - */ - private Map extractNfxAttributes(javafx.scene.Node node) { - Map result = new HashMap<>(); - node.getProperties().forEach((k, v) -> { - if (k instanceof String key && key.startsWith("nfx:") && v instanceof String value) { - result.put(key, value); + private static Class getPropertyType(Property prop) { + try { + Method getter = prop.getClass().getMethod("get"); + return getter.getReturnType(); + } catch (Exception e) { + return Object.class; // Fallback + } + } + + private static Object resolveExpression(@NotNull String expr, @NotNull Map namespace) throws Exception { + // z.B. "viewModel.username" + String[] parts = expr.split("\\."); + Object current = namespace.get(parts[0]); + for (int i = 1; i < parts.length; i++) { + String getter = "get" + Character.toUpperCase(parts[i].charAt(0)) + parts[i].substring(1); + current = current.getClass().getMethod(getter).invoke(current); + } + return current; + } + + private static @NotNull List collectAllNodes(Node root) { + List nodes = new ArrayList<>(); + nodes.add(root); + if (root instanceof Parent parent && !(root instanceof FxmlComponent)) { + for (Node child : parent.getChildrenUnmodifiable()) { + nodes.addAll(collectAllNodes(child)); } - }); - return result; + } + return nodes; } /** @@ -128,61 +191,4 @@ public class ComponentLoader { } // Additional control types (e.g., CheckBox, ComboBox) can be added here } - - private String preprocessNfxAttributes(String fxmlPath) { - try { - nfxBindingMap.clear(); - var factory = javax.xml.parsers.DocumentBuilderFactory.newInstance(); - var builder = factory.newDocumentBuilder(); - var doc = builder.parse(getClass().getResourceAsStream(fxmlPath)); - var all = doc.getElementsByTagName("*"); - - int autoId = 0; - for (int i = 0; i < all.getLength(); i++) { - var el = (org.w3c.dom.Element) all.item(i); - Map nfxAttrs = new HashMap<>(); - var attrs = el.getAttributes(); - - List toRemove = new ArrayList<>(); - for (int j = 0; j < attrs.getLength(); j++) { - var attr = (org.w3c.dom.Attr) attrs.item(j); - if (attr.getName().startsWith("nfx:")) { - nfxAttrs.put(attr.getName(), attr.getValue()); - toRemove.add(attr.getName()); - } - } - - if (!nfxAttrs.isEmpty()) { - String fxid = el.getAttribute("fx:id"); - if (fxid == null || fxid.isBlank()) { - fxid = "auto_id_" + (++autoId); - el.setAttribute("fx:id", fxid); - } - nfxBindingMap.put(fxid, nfxAttrs); - toRemove.forEach(el::removeAttribute); - } - } - - // Speichere das bereinigte Dokument als temporäre Datei - File tempFile = File.createTempFile("cleaned_fxml", ".fxml"); - tempFile.deleteOnExit(); - var transformer = javax.xml.transform.TransformerFactory.newInstance().newTransformer(); - transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes"); - transformer.transform(new javax.xml.transform.dom.DOMSource(doc), - new javax.xml.transform.stream.StreamResult(tempFile)); - - return tempFile.toURI().toString(); - } catch (Exception e) { - throw new RuntimeException("Preprocessing failed for: " + fxmlPath, e); - } - } - - private Map lookupNfxAttributes(javafx.scene.Node node, FXMLLoader loader) { - String fxid = loader.getNamespace().entrySet().stream() - .filter(e -> e.getValue() == node) - .map(Map.Entry::getKey) - .findFirst().orElse(null); - if (fxid == null) return Map.of(); - return nfxBindingMap.getOrDefault(fxid, Map.of()); - } } diff --git a/fx/src/main/java/de/neitzel/fx/component/controls/Binding.java b/fx/src/main/java/de/neitzel/fx/component/controls/Binding.java index f4dc831..ffafadd 100644 --- a/fx/src/main/java/de/neitzel/fx/component/controls/Binding.java +++ b/fx/src/main/java/de/neitzel/fx/component/controls/Binding.java @@ -10,15 +10,15 @@ import javafx.scene.layout.Region; * of {@link BindingData} objects. It extends the {@link Region} class and * provides functionality to bind and monitor connections between source * and target properties. - * + *

* The primary purpose of this control is to maintain an observable list * of bindings, allowing developers to track or adjust the linked properties * dynamically. - * + *

* The internal list of bindings is implemented as an {@link ObservableList}, * allowing property change notifications to be easily monitored for UI * updates or other reactive behaviors. - * + *

* This class serves as an organizational component and does not provide * any user interaction by default. */ @@ -28,17 +28,32 @@ public class Binding extends Region { * Represents an observable list of {@link BindingData} objects contained within the * {@link Binding} instance. This list is utilized to manage and monitor * the bindings between source and target properties dynamically. - * + *

* The list is implemented as an {@link ObservableList}, allowing changes in the * collection to be observed and reacted to, such as triggering UI updates or * responding to binding modifications. - * + *

* This field is initialized as an empty list using {@link FXCollections#observableArrayList()}. * It is declared as final to ensure its reference cannot be changed, while the * contents of the list remain mutable. */ private final ObservableList bindings = FXCollections.observableArrayList(); + /** + * Constructs a new instance of the BindingControl class. + *

+ * This default constructor initializes the BindingControl without + * any pre-configured bindings. The instance will contain an empty + * {@link ObservableList} of {@link BindingData} objects, which can later + * be populated as needed. + *

+ * The constructor does not perform additional setup or initialization, + * allowing the class to be extended or customized as necessary. + */ + public Binding() { + // Empty, the ComponentLoader is used to work on the bindings. + } + /** * Retrieves the observable list of {@code Binding} objects associated with this control. * The returned list allows monitoring and management of the bindings maintained @@ -49,19 +64,4 @@ public class Binding extends Region { public ObservableList getBindings() { return bindings; } - - /** - * Constructs a new instance of the BindingControl class. - * - * This default constructor initializes the BindingControl without - * any pre-configured bindings. The instance will contain an empty - * {@link ObservableList} of {@link BindingData} objects, which can later - * be populated as needed. - * - * The constructor does not perform additional setup or initialization, - * allowing the class to be extended or customized as necessary. - */ - public Binding() { - // Absichtlich leer – wird später "ausgewertet" - } } \ No newline at end of file diff --git a/fx/src/main/java/de/neitzel/fx/component/controls/FxmlComponent.java b/fx/src/main/java/de/neitzel/fx/component/controls/FxmlComponent.java index a871db4..635910f 100644 --- a/fx/src/main/java/de/neitzel/fx/component/controls/FxmlComponent.java +++ b/fx/src/main/java/de/neitzel/fx/component/controls/FxmlComponent.java @@ -9,27 +9,16 @@ import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.layout.StackPane; -import java.io.IOException; import java.util.Arrays; public class FxmlComponent extends StackPane { private final StringProperty fxml = new SimpleStringProperty(); + private final StringProperty direction = new SimpleStringProperty("unidirectional"); + private final ObjectProperty data = new SimpleObjectProperty<>(); - public StringProperty fxmlProperty() { return fxml; } - public String getFxml() { return fxml.get(); } - public void setFxml(String fxml) { this.fxml.set(fxml); } - - public StringProperty directionProperty() { return direction; } - public String getDirection() { return direction.get(); } - public void setDirection(String direction) { this.direction.set(direction); } - - public ObjectProperty dataProperty() { return data; } - public Object getData() { return data.get(); } - public void setData(Object data) { this.data.set(data); } - public FxmlComponent() { fxml.addListener((obs, oldVal, newVal) -> load()); data.addListener((obs, oldVal, newVal) -> injectData()); @@ -37,20 +26,14 @@ public class FxmlComponent extends StackPane { private void load() { if (getFxml() == null || getFxml().isBlank()) return; - try { - ComponentLoader loader = new ComponentLoader(); - // Option: ControllerFactory verwenden, wenn nötig - Parent content = loader.load(getClass().getResource(getFxml())); + ComponentLoader loader = new ComponentLoader(); + Parent content = loader.load(getClass().getResource(getFxml())); - getChildren().setAll(content); + getChildren().setAll(content); - Object controller = loader.getController(); - if (controller != null && getData() != null) { - injectDataToController(controller, getData()); - } - - } catch (IOException e) { - e.printStackTrace(); + Object controller = loader.getController(); + if (controller != null && getData() != null) { + injectDataToController(controller, getData()); } } @@ -63,6 +46,22 @@ public class FxmlComponent extends StackPane { } } + public String getFxml() { + return fxml.get(); + } + + public void setFxml(String fxml) { + this.fxml.set(fxml); + } + + public Object getData() { + return data.get(); + } + + public void setData(Object data) { + this.data.set(data); + } + private void injectDataToController(Object controller, Object dataObject) { // Daten-Objekt per Reflection zuweisen // Beispiel: Controller hat `setData(User data)` @@ -86,5 +85,25 @@ public class FxmlComponent extends StackPane { } return null; } + + public StringProperty fxmlProperty() { + return fxml; + } + + public StringProperty directionProperty() { + return direction; + } + + public String getDirection() { + return direction.get(); + } + + public void setDirection(String direction) { + this.direction.set(direction); + } + + public ObjectProperty dataProperty() { + return data; + } } diff --git a/fx/src/main/java/de/neitzel/fx/component/model/BindingData.java b/fx/src/main/java/de/neitzel/fx/component/model/BindingData.java index 6c7ba64..8b65618 100644 --- a/fx/src/main/java/de/neitzel/fx/component/model/BindingData.java +++ b/fx/src/main/java/de/neitzel/fx/component/model/BindingData.java @@ -26,6 +26,7 @@ public class BindingData { * within the JavaFX property system. */ private StringProperty direction = new SimpleStringProperty("unidirectional"); + /** * Represents the source of the binding. This property holds a string value * that specifies the originating object or identifier in the binding connection. -- 2.47.1 From 6c1338d1718119053edfc411ba4c5e10229457bd Mon Sep 17 00:00:00 2001 From: Konrad Neitzel Date: Tue, 1 Jul 2025 15:50:03 +0200 Subject: [PATCH 4/8] Added JsonConfiguration --- .../gson/config/JsonConfiguration.java | 270 ++++++++++++++++++ .../gson/config/JsonConfigurationTest.java | 128 +++++++++ 2 files changed, 398 insertions(+) create mode 100644 gson/src/main/java/de/neitzel/gson/config/JsonConfiguration.java create mode 100644 gson/src/test/java/de/neitzel/gson/config/JsonConfigurationTest.java diff --git a/gson/src/main/java/de/neitzel/gson/config/JsonConfiguration.java b/gson/src/main/java/de/neitzel/gson/config/JsonConfiguration.java new file mode 100644 index 0000000..ec43e0b --- /dev/null +++ b/gson/src/main/java/de/neitzel/gson/config/JsonConfiguration.java @@ -0,0 +1,270 @@ +package de.neitzel.gson.config; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import lombok.Builder; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +/** + * Represents a configuration utility class that manages application settings and allows + * loading and saving the configuration in JSON format. This class is built using Gson for + * JSON serialization and deserialization. + *

+ * The class maintains application settings in memory and provides methods to store + * the configuration on the filesystem and retrieve it as needed. + */ +@Builder(builderClassName = "ConfigurationBuilder") +public class JsonConfiguration { + + /** + * The name of the application. + * This variable is used to identify the application and is incorporated into various configurations, + * such as the naming of directories or files associated with the application's settings. + * It is finalized and set during the construction of the {@code JsonConfiguration} instance and cannot be changed afterward. + */ + private final String appName; + + /** + * The filesystem path representing the home directory utilized by the application. + * This directory serves as the location where application-specific configuration files + * and data are stored. The path is initialized when the {@code JsonConfiguration} instance + * is constructed, based on the settings provided through the {@code JsonConfigurationBuilder}. + * It can be customized to a user-specified value or defaults to the user's home directory. + *

+ * The {@code homeDir} variable is integral in determining the location of the main configuration + * file and other related resources used by the application. + */ + private final String homeDir; + + /** + * A map that stores configuration settings as key-value pairs, + * where both the keys and values are represented as strings. + *

+ * This map is used to manage dynamic or runtime settings for the configuration, + * allowing for flexible assignment and retrieval of values associated with specific + * configuration keys. It is initialized as a final instance, ensuring it cannot be + * reassigned after creation. + */ + private final Map settings; + + /** + * A Gson instance used for handling JSON serialization and deserialization within + * the JsonConfiguration class. This instance is immutable and customized with + * registered adapters during the initialization of the JsonConfiguration. + *

+ * The Gson object provides functionality for converting Java objects to JSON + * and vice versa. It supports complex serialization and deserialization + * workflows by leveraging adapters specified during the configuration phase. + *

+ * Adapters can be registered to customize the behavior of (de)serialization + * for specific types. + */ + private final Gson gson; + + /** + * Stores a key-value pair into the configuration settings. + * The value is serialized into a JSON string before being stored. + * + * @param key the key under which the value will be stored + * @param value the object to be associated with the specified key + */ + public void set(String key, Object value) { + settings.put(key, gson.toJson(value)); + } + + /** + * Retrieves a value associated with the specified key from the configuration, + * deserializing it into the specified class type using Gson. + * If the key does not exist in the settings, the method returns {@code null}. + * + * @param the type of the object to be deserialized + * @param key the key corresponding to the value in the configuration + * @param clazz the {@code Class} object representing the expected type of the value + * @return the deserialized object of type {@code T}, or {@code null} + * if the key does not exist + */ + public T get(String key, Class clazz) { + String json = settings.get(key); + return json != null ? gson.fromJson(json, clazz) : null; + } + + /** + * Retrieves a value associated with the given key from the configuration as an object of the specified type. + * If the key does not exist in the configuration, the provided default value is returned. + * + * @param the type of the object to be returned + * @param key the key whose associated value is to be retrieved + * @param clazz the class of the object to deserialize the value into + * @param defaultValue the default value to return if the key does not exist or the value is null + * @return the value associated with the specified key, deserialized into the specified type, + * or the default value if the key does not exist or the value is null + */ + public T get(String key, Class clazz, T defaultValue) { + String json = settings.get(key); + return json != null ? gson.fromJson(json, clazz) : defaultValue; + } + + /** + * Loads the configuration data from the JSON configuration file located at the path + * determined by the {@code getConfigFilePath()} method. + * If the configuration file exists, its content is read and deserialized into a map + * of key-value pairs using Gson. The method clears the current settings and populates + * them with the loaded values. + * + * @throws IOException if an I/O error occurs while reading the configuration file + */ + public void load() throws IOException { + Path configPath = getConfigFilePath(); + if (Files.exists(configPath)) { + try (var reader = Files.newBufferedReader(configPath)) { + Map loaded = gson.fromJson(reader, new TypeToken>() { + }.getType()); + settings.clear(); + settings.putAll(loaded); + } + } + } + + /** + * Constructs the path to the configuration file for the application. + * The configuration file is located in the user's home directory, within a hidden + * folder named after the application, and is named "config.json". + * + * @return the {@code Path} to the application's configuration file + */ + private Path getConfigFilePath() { + return Path.of(homeDir, "." + appName, "config.json"); + } + + /** + * Saves the current configuration to a JSON file. + *

+ * This method serializes the current settings into a JSON format and writes + * them to a file located at the configuration path. If the parent directory + * of the configuration file does not exist, it is created automatically. + *

+ * The configuration file path is determined based on the application name + * and home directory. Any existing content in the file will be overwritten + * during this operation. + * + * @throws IOException if an I/O error occurs while creating the directory, + * opening the file, or writing to the file + */ + public void save() throws IOException { + Path configPath = getConfigFilePath(); + Files.createDirectories(configPath.getParent()); + try (var writer = Files.newBufferedWriter(configPath)) { + gson.toJson(settings, writer); + } + } + + /** + * Builder class for creating instances of {@code JsonConfiguration}. + * The {@code JsonConfigurationBuilder} allows the configuration of application + * name, home directory, and custom Gson adapters before building a {@code JsonConfiguration} object. + */ + public static class JsonConfigurationBuilder { + /** + * A map that holds custom Gson adapters to register with a GsonBuilder. + * The keys represent the classes for which the adapters are applicable, + * and the values are the adapter instances associated with those classes. + *

+ * This variable is used to store user-defined type adapters, allowing + * for customized serialization and deserialization behavior for specific + * classes when constructing a {@code JsonConfiguration}. + *

+ * It is populated using the {@code addGsonAdapter} method in the + * {@code JsonConfigurationBuilder} class and is later passed to a + * {@code GsonBuilder} for registration. + */ + private final Map, Object> gsonAdapters = new HashMap<>(); + + /** + * The name of the application being configured. + * This variable holds a string representation of the application's name and is used + * to identify the application within the context of the {@code JsonConfiguration}. + * It is set during the construction of a {@code JsonConfigurationBuilder} instance. + */ + private String appName; + + /** + * Represents the home directory path of the current user. + * By default, this variable is initialized to the value of the "user.home" system property, + * which typically points to the user's home directory on the filesystem. + *

+ * This field can be customized to point to a different directory via the builder class + * methods when building an instance of {@code JsonConfiguration}. + *

+ * Example system values for "user.home" may include paths such as "~/Users/username" for macOS, + * "C:/Users/username" for Windows, or "/home/username" for Unix/Linux systems. + */ + private String homeDir = System.getProperty("user.home"); + + /** + * Sets the application name to be used in the configuration. + * + * @param appName the name of the application to be set + * @return the current instance of {@code JsonConfigurationBuilder} for chaining + */ + public JsonConfigurationBuilder appName(String appName) { + this.appName = appName; + return this; + } + + /** + * Sets the home directory for the configuration being built. + * This method specifies the directory path where the application's configuration + * files or settings should be stored. + * + * @param homeDir the path to the desired home directory + * @return the current instance of {@code JsonConfigurationBuilder} to enable method chaining + */ + public JsonConfigurationBuilder homeDir(String homeDir) { + this.homeDir = homeDir; + return this; + } + + /** + * Adds a custom Gson adapter to the builder for the specified type. + * This method allows registration of a type-to-adapter mapping that will be applied + * when building the Gson instance within the {@code JsonConfiguration}. + * + * @param type the {@code Class} of the type for which the adapter is being registered + * @param adapter the adapter object to be used for the specified type + * @return the current instance of {@code JsonConfigurationBuilder}, allowing method chaining + */ + public JsonConfigurationBuilder addGsonAdapter(Class type, Object adapter) { + gsonAdapters.put(type, adapter); + return this; + } + + /** + * Builds and returns an instance of {@code JsonConfiguration} with the specified + * settings, including the application name, home directory, and any registered + * custom Gson adapters. + * + * @return a {@code JsonConfiguration} instance configured with the builder's parameters. + */ + public JsonConfiguration build() { + GsonBuilder gsonBuilder = new GsonBuilder(); + for (var entry : gsonAdapters.entrySet()) { + gsonBuilder.registerTypeAdapter(entry.getKey(), entry.getValue()); + } + + Gson gson = gsonBuilder.create(); + + return new JsonConfiguration( + appName, + homeDir, + new HashMap<>(), + gson + ); + } + } +} diff --git a/gson/src/test/java/de/neitzel/gson/config/JsonConfigurationTest.java b/gson/src/test/java/de/neitzel/gson/config/JsonConfigurationTest.java new file mode 100644 index 0000000..b95508b --- /dev/null +++ b/gson/src/test/java/de/neitzel/gson/config/JsonConfigurationTest.java @@ -0,0 +1,128 @@ +package de.neitzel.gson.config; + +import com.google.gson.Gson; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +class JsonConfigurationTest { + + /** + * Test class for JsonConfiguration containing unit tests for the `get` method. + * The `get` method fetches the value associated with a given key and converts + * it from JSON representation to the specified class type. + */ + + @Test + void testGetExistingKeyWithValidValue() { + // Arrange + Gson gson = new Gson(); + HashMap settings = new HashMap<>(); + settings.put("testKey", gson.toJson(42)); + JsonConfiguration jsonConfiguration = JsonConfiguration.builder() + .settings(settings) + .gson(gson) + .build(); + + // Act + Integer value = jsonConfiguration.get("testKey", Integer.class); + + // Assert + assertEquals(42, value); + } + + @Test + void testGetNonExistingKey() { + // Arrange + Gson gson = new Gson(); + HashMap settings = new HashMap<>(); + JsonConfiguration jsonConfiguration = JsonConfiguration.builder() + .settings(settings) + .gson(gson) + .build(); + + // Act + String value = jsonConfiguration.get("nonExistentKey", String.class); + + // Assert + assertNull(value); + } + + @Test + void testGetWithDefaultValueWhenKeyExists() { + // Arrange + Gson gson = new Gson(); + HashMap settings = new HashMap<>(); + settings.put("testKey", gson.toJson("Hello World")); + JsonConfiguration jsonConfiguration = JsonConfiguration.builder() + .settings(settings) + .gson(gson) + .build(); + + // Act + String value = jsonConfiguration.get("testKey", String.class, "Default Value"); + + // Assert + assertEquals("Hello World", value); + } + + @Test + void testGetWithDefaultValueWhenKeyDoesNotExist() { + // Arrange + Gson gson = new Gson(); + HashMap settings = new HashMap<>(); + JsonConfiguration jsonConfiguration = JsonConfiguration.builder() + .settings(settings) + .gson(gson) + .build(); + + // Act + String value = jsonConfiguration.get("nonExistentKey", String.class, "Default Value"); + + // Assert + assertEquals("Default Value", value); + } + + @Test + void testGetWithComplexObject() { + // Arrange + Gson gson = new Gson(); + HashMap settings = new HashMap<>(); + TestObject testObject = new TestObject("John Doe", 30); + settings.put("complexKey", gson.toJson(testObject)); + JsonConfiguration jsonConfiguration = JsonConfiguration.builder() + .settings(settings) + .gson(gson) + .build(); + + // Act + TestObject result = jsonConfiguration.get("complexKey", TestObject.class); + + // Assert + assertEquals("John Doe", result.name()); + assertEquals(30, result.age()); + } + + // Helper class for complex object tests + static class TestObject { + private final String name; + + private final int age; + + TestObject(String name, int age) { + this.name = name; + this.age = age; + } + + public String name() { + return name; + } + + public int age() { + return age; + } + } +} \ No newline at end of file -- 2.47.1 From 93de125e671d6112581a0a7c455d90e58c4a5e62 Mon Sep 17 00:00:00 2001 From: Konrad Neitzel Date: Sat, 29 Nov 2025 22:47:48 +0100 Subject: [PATCH 5/8] Add guidelines for Copilot usage and commit messages Updated dependencies and use Java 25. --- .github/JavaDoc-rules.md | 15 ++++++++++++ .github/copilot-instructions.md | 9 +++++++ .github/git-commit-instructions.md | 9 +++++++ .github/prompts/TEST.prompt.md | 1 + .mvn/wrapper/maven-wrapper.properties | 2 +- pom.xml | 34 +++++++++++++-------------- 6 files changed, 52 insertions(+), 18 deletions(-) create mode 100644 .github/JavaDoc-rules.md create mode 100644 .github/copilot-instructions.md create mode 100644 .github/git-commit-instructions.md create mode 100644 .github/prompts/TEST.prompt.md diff --git a/.github/JavaDoc-rules.md b/.github/JavaDoc-rules.md new file mode 100644 index 0000000..3e2a8e0 --- /dev/null +++ b/.github/JavaDoc-rules.md @@ -0,0 +1,15 @@ +JavaDoc should be included for: +[]: # - All public, protected and private classes and interfaces +[]: # - All public, protected and private methods and constructors +[]: # - Any method that overrides a superclass method +[]: # 3. If JavaDoc is missing, please add it following these guidelines: +[]: # - Use clear and concise language to describe the purpose and functionality. +[]: # - Include descriptions for all parameters using @param tags. +[]: # - Include a description of the return value using @return tags. +[]: # - Mention any exceptions that the method might throw using @throws tags. +[]: # - Follow standard JavaDoc formatting conventions. +[]: # 4. After adding JavaDoc, review it for clarity and completeness. +[]: # 5. Commit your changes with a message indicating that JavaDoc has been added or updated. +[]: # +[]: # By following these instructions, we can ensure that our codebase remains well-documented and easy to understand +for all contributors. \ No newline at end of file diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..9fa4d63 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,9 @@ +When working on a prompt, please follow these instructions: + +1. When creating Code then just create the code required to complete the task. Do not include any explanations, + comments, or other text. +2. After code changes, check if any JavaDoc is missing. Please see JavaDoc-rules.md for guidelines on adding JavaDoc. +3. Create Unit Tests for the code you created or modified. Ensure that the tests cover various scenarios and edge cases. +4. When writing commit messages, please follow the guidelines in git-commit-instructions.md to ensure clarity and + consistency. +5. Ensure that your code adheres to the project's coding standards and best practices. \ No newline at end of file diff --git a/.github/git-commit-instructions.md b/.github/git-commit-instructions.md new file mode 100644 index 0000000..c20de76 --- /dev/null +++ b/.github/git-commit-instructions.md @@ -0,0 +1,9 @@ +# Git Commit Message Guidelines + +When creating a commit message, please follow these guidelines to ensure clarity and consistency across the project: + +1. **Structure of Commit Message**: + - The commit message should consist of a header, a body (optional), and a footer (optional). + - The header should be a single line that summarizes the changes made. + - If necessary, the body can provide additional context or details about the changes. + - The footer can include references to issues or breaking changes. \ No newline at end of file diff --git a/.github/prompts/TEST.prompt.md b/.github/prompts/TEST.prompt.md new file mode 100644 index 0000000..c9158de --- /dev/null +++ b/.github/prompts/TEST.prompt.md @@ -0,0 +1 @@ +Please just respond with "Hello, World!" \ No newline at end of file diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 6f40a26..524ccf2 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/pom.xml b/pom.xml index 374fd26..0a38ec7 100644 --- a/pom.xml +++ b/pom.xml @@ -22,38 +22,38 @@ - 21 + 25 3.8.6 - 21.0.3 + 25.0.1 26.0.2 - 5.12.1 - 1.18.38 - 5.16.1 + 6.0.1 + 1.18.42 + 5.20.0 0.10.2 2.0.17 - 2.16.2 + 2.20.1 0.0.8 0.1.5 - 3.3.2 - 3.13.0 + 3.5.0 + 3.14.1 3.6.1 - 3.1.2 + 3.1.4 3.4.1 3.1.2 - 3.4.1 - 3.6.3 - 3.5.0 - 3.3.1 + 3.5.0 + 3.12.0 + 3.9.0 + 3.4.0 3.5.3 - 4.0.0-M14 - 3.2.5 + 4.0.0-M16 + 3.5.4 1.0.0.RC2 - 3.22.0 - 4.8.5.0 + 3.28.0 + 4.9.8.2 pmd -- 2.47.1 From 5503dd192e19010cf59b18639d36df0d642b8f4e Mon Sep 17 00:00:00 2001 From: Konrad Neitzel Date: Sun, 30 Nov 2025 18:58:05 +0100 Subject: [PATCH 6/8] Work in progress ... --- README.md | 21 +- core/pom.xml | 4 +- .../core/commandline/ArgumentProvider.java | 65 +- .../neitzel/core/commandline/Parameter.java | 278 +- .../de/neitzel/core/commandline/Parser.java | 115 +- .../de/neitzel/core/image/ImageScaler.java | 108 +- .../core/inject/ApplicationContext.java | 22 +- .../de/neitzel/core/inject/ComponentData.java | 16 +- .../neitzel/core/inject/ComponentScanner.java | 122 +- .../core/inject/annotation/Component.java | 6 +- .../core/inject/annotation/Config.java | 10 +- .../core/inject/annotation/Inject.java | 4 +- .../core/io/ConvertedEncodingFileReader.java | 6 +- .../java/de/neitzel/core/io/FileUtils.java | 10 +- .../de/neitzel/core/io/StringEncoder.java | 20 +- .../de/neitzel/core/sound/ToneGenerator.java | 32 +- .../java/de/neitzel/core/sound/ToneTable.java | 29 +- .../main/java/de/neitzel/core/sql/Query.java | 600 +- .../neitzel/core/sql/TrimmingResultSet.java | 5307 +++++++++-------- .../java/de/neitzel/core/util/ArrayUtils.java | 20 +- .../java/de/neitzel/core/util/EnumUtil.java | 18 +- .../core/util/RegionalizationMessage.java | 38 +- .../java/de/neitzel/core/util/StopWatch.java | 240 +- .../java/de/neitzel/core/util/Strings.java | 70 +- .../java/de/neitzel/core/util/XmlUtils.java | 380 +- .../InjectableComponentScannerTest.java | 6 +- encryption/pom.xml | 4 +- .../de/neitzel/encryption/BaseAlphabet.java | 25 +- .../de/neitzel/encryption/FF1Encryption.java | 115 +- .../de/neitzel/encryption/MainAlphabet.java | 37 +- .../de/neitzel/encryption/MainDomain.java | 34 + fx-example/pom.xml | 4 +- .../neitzel/fx/component/example/Address.java | 18 + .../fx/component/example/ExampleApp.java | 28 +- .../de/neitzel/fx/component/example/Main.java | 9 + .../neitzel/fx/component/example/Person.java | 18 + .../fx/injectfx/example/JavaFXApp.java | 53 +- .../de/neitzel/fx/injectfx/example/Main.java | 18 + .../fx/injectfx/example/MainWindow.java | 36 + fx-example/src/main/resources/address.fxml | 4 +- .../fx/injectfx/example/MainWindow.fxml | 12 +- fx-example/src/main/resources/person.fxml | 4 +- fx/pom.xml | 4 +- .../neitzel/fx/component/AutoViewModel.java | 87 +- .../neitzel/fx/component/ComponentLoader.java | 92 +- .../fx/component/controls/FxmlComponent.java | 98 +- .../fx/component/model/BindingData.java | 42 +- .../fx/injectfx/FXMLComponentInstances.java | 4 +- .../injectfx/InjectingControllerFactory.java | 32 +- .../fx/injectfx/InjectingFXMLLoader.java | 18 +- .../fx/mvvm/BindingAwareFXMLLoader.java | 8 +- .../fx/mvvm/GenericViewController.java | 22 +- .../de/neitzel/fx/mvvm/GenericViewModel.java | 14 +- gson/pom.xml | 4 +- .../gson/adapter/ExcludeFieldsAdapter.java | 211 +- .../gson/adapter/InstantTypeAdapter.java | 68 +- log4j/pom.xml | 4 +- .../java/de/neitzel/log4j/Log4jUtils.java | 59 +- net/pom.xml | 4 +- .../java/de/neitzel/net/imap/ImapAccount.java | 145 +- .../neitzel/net/imap/ImapAccountMonitor.java | 104 +- .../de/neitzel/net/imap/NewEmailEvent.java | 4 +- .../de/neitzel/net/mail/MessageUtils.java | 97 +- pmd-ruleset.xml | 22 +- 64 files changed, 4856 insertions(+), 4253 deletions(-) diff --git a/README.md b/README.md index 7063983..d041f20 100644 --- a/README.md +++ b/README.md @@ -2,24 +2,32 @@ ## A Java Utilities Library -This repository is **not** a production-ready library, but rather a personal collection of small helpers, utilities, and ideas that I find useful or interesting as a Java developer. +This repository is **not** a production-ready library, but rather a personal collection of small helpers, utilities, and +ideas that I find useful or interesting as a Java developer. -It serves primarily as a **knowledge base** and **inspiration pool** for my own development work. You're welcome to explore, copy, modify, or improve whatever you find helpful. +It serves primarily as a **knowledge base** and **inspiration pool** for my own development work. You're welcome to +explore, copy, modify, or improve whatever you find helpful. > ⚠️ Use at your own discretion — no guarantees of stability, backwards compatibility, or completeness. --- ## License -This is free and unencumbered software released into the public domain. Please see the [License](LICENSE.md) for details. + +This is free and unencumbered software released into the public domain. Please see the [License](LICENSE.md) for +details. --- ## Note on Content -The content of this repository — including source code, documentation, and examples — was partially created with the assistance of ChatGPT (an AI model by OpenAI). The generated content has been reviewed, edited, and integrated into the overall context by me. +The content of this repository — including source code, documentation, and examples — was partially created with the +assistance of ChatGPT (an AI model by OpenAI). The generated content has been reviewed, edited, and integrated into the +overall context by me. -Responsibility for all content lies entirely with me. Any generated content is subject to [OpenAI’s Terms of Use](https://openai.com/policies/terms-of-use) and is — where possible — either in the public domain or usable under a license compatible with this project's license. +Responsibility for all content lies entirely with me. Any generated content is subject +to [OpenAI’s Terms of Use](https://openai.com/policies/terms-of-use) and is — where possible — either in the public +domain or usable under a license compatible with this project's license. ## Components @@ -47,7 +55,8 @@ TypeAdapter for gson. ### log4j -Stuff for log4j (Version 1). Please use log4j2 if you want to use log4j! (Or log with slf4j as I do in all other modules!) +Stuff for log4j (Version 1). Please use log4j2 if you want to use log4j! (Or log with slf4j as I do in all other +modules!) ### net diff --git a/core/pom.xml b/core/pom.xml index 0e57f51..683a2c2 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -1,6 +1,6 @@ - 4.0.0 diff --git a/core/src/main/java/de/neitzel/core/commandline/ArgumentProvider.java b/core/src/main/java/de/neitzel/core/commandline/ArgumentProvider.java index c4906b4..f8b2de4 100644 --- a/core/src/main/java/de/neitzel/core/commandline/ArgumentProvider.java +++ b/core/src/main/java/de/neitzel/core/commandline/ArgumentProvider.java @@ -6,10 +6,10 @@ import java.util.Iterator; * The ArgumentProvider class is a helper utility for iterating over an array * of command-line arguments. It provides methods to check for available arguments * and retrieve them in sequence. - * - * This class is designed to work seamlessly with a command-line parser - * and handle tokenized inputs efficiently. It implements the Iterator interface - * for ease of iteration. + *

+ * This class is designed to work seamlessly with a command-line parser and handle + * tokenized inputs efficiently. It implements the {@link Iterator} interface for ease + * of iteration and provides convenience methods for peeking ahead. */ public class ArgumentProvider implements Iterator { @@ -19,18 +19,15 @@ public class ArgumentProvider implements Iterator { * and processing by the application logic. It is used within the {@code ArgumentProvider} * class to iterate through and retrieve arguments systematically. */ - private String[] arguments; + private final String[] arguments; /** * Tracks the current position within an array of arguments. - * - * This variable is used to index into the arguments array, enabling - * sequential access to command-line tokens. It is incremented as arguments - * are processed or retrieved using methods such as {@code next()} or {@code peek()} - * in the {@link ArgumentProvider} class. - * - * Its value starts at 0 and increases until it reaches the length of - * the provided arguments array, at which point iteration ends. + * This variable is used to index into the arguments array, enabling sequential access + * to command-line tokens. It is incremented as arguments are processed or retrieved + * using methods such as {@code next()} or {@code peek()} in the {@link ArgumentProvider} + * class. Its value starts at 0 and increases until it reaches the length of the provided + * arguments array, at which point iteration ends. */ private int current = 0; @@ -43,21 +40,12 @@ public class ArgumentProvider implements Iterator { */ public ArgumentProvider(final String[] arguments) { if (arguments == null) { - this.arguments = new String[] {}; + this.arguments = new String[]{}; } else { this.arguments = arguments; } } - /** - * Checks if there are more arguments available to iterate over. - * - * @return true if there are additional arguments available; false otherwise. - */ - public boolean hasNext() { - return current < arguments.length; - } - /** * Determines if the specified number of additional arguments are available in the collection. * @@ -68,6 +56,26 @@ public class ArgumentProvider implements Iterator { return current + count <= arguments.length; } + /** + * Returns the next argument in the sequence without advancing the iterator. + * If there are no more arguments available, this method returns null. + * + * @return the next argument in the sequence or null if no arguments are available + */ + public String peek() { + if (!hasNext()) return null; + return arguments[current]; + } + + /** + * Checks if there are more arguments available to iterate over. + * + * @return true if there are additional arguments available; false otherwise. + */ + public boolean hasNext() { + return current < arguments.length; + } + /** * Retrieves the next argument in the sequence. * If no more arguments are available, returns {@code null}. @@ -81,15 +89,4 @@ public class ArgumentProvider implements Iterator { current++; return result; } - - /** - * Returns the next argument in the sequence without advancing the iterator. - * If there are no more arguments available, this method returns null. - * - * @return the next argument in the sequence or null if no arguments are available - */ - public String peek() { - if (!hasNext()) return null; - return arguments[current]; - } } diff --git a/core/src/main/java/de/neitzel/core/commandline/Parameter.java b/core/src/main/java/de/neitzel/core/commandline/Parameter.java index 5875f89..f2f70bd 100644 --- a/core/src/main/java/de/neitzel/core/commandline/Parameter.java +++ b/core/src/main/java/de/neitzel/core/commandline/Parameter.java @@ -13,7 +13,7 @@ import java.util.function.Consumer; * The `Parameter` class defines a command-line parameter with associated metadata, * such as constraints on the number of values it accepts, descriptions, and aliases. * It also allows specifying callbacks to handle parameter processing. - * + *

* This class is intended to be used as part of a command-line parser, enabling * structured handling of arguments provided via the command line. */ @@ -23,14 +23,141 @@ import java.util.function.Consumer; @Setter public class Parameter { + /** + * The `name` variable represents the primary identifier for a parameter. + * This string is used to uniquely identify a command-line parameter when parsing + * arguments. It serves as the key for registering and retrieving parameters in a + * command-line parser. + *

+ * The value of `name` is case-insensitive and can be used alongside aliases to + * recognize and process parameters provided in the command-line input. + */ + private String name; + + /** + * Specifies the minimum number of values required for this parameter. + *

+ * This variable enforces a constraint on the number of arguments that must + * be provided for the parameter during command-line parsing. If the number of + * provided arguments is less than this value, an exception will be thrown during parsing. + *

+ * It is primarily used in validation logic within the command-line parser + * to ensure the required input is received for proper processing of the parameter. + */ + private int minNumberValues; + + /** + * Specifies the maximum number of values that the corresponding parameter can accept. + *

+ * This field is used to validate and enforce constraints during command-line parsing. + * If more values than specified are provided for a parameter, the parser throws an exception + * to indicate a violation of this constraint. + *

+ * A value of 0 implies that the parameter does not support any values, while a positive + * value indicates the exact maximum limit of acceptable values. + */ + private int maxNumberValues; + + /** + * Indicates whether the parameter allows multiple entries. + *

+ * If set to {@code true}, the parameter can be specified multiple times + * on the command-line. This allows the association of multiple values + * or options with the same parameter name. + *

+ * If set to {@code false}, the parameter can be specified only once + * during command-line parsing. + */ + private boolean multipleEntries; + + /** + * A concise, human-readable description of the parameter's purpose and functionality. + *

+ * This description provides a brief summary to help users understand the + * essential role of the parameter within the command-line parser. It is typically + * displayed in usage instructions, help messages, or command summaries. + */ + private String shortDescription; + + /** + * A detailed, extended description of the parameter's purpose and usage. + *

+ * This description provides deeper context about what the parameter represents, + * how it fits into the overall command-line application, and any nuances + * associated with its use. It is displayed when help or additional documentation + * for a specific parameter is requested. + */ + private String longDescription; + + /** + * A callback function that processes a list of string arguments for a specific parameter. + * The callback is invoked during command-line parsing when a parameter is recognized, + * passing the associated values of the parameter for further processing. + *

+ * The provided {@link Consumer} implementation defines the logic to + * handle or validate the values supplied for a command-line parameter. The values + * passed are determined based on the parameter's configuration (e.g., minimum and + * maximum number of associated values). + *

+ * This field is typically set for the `Parameter` class to enable custom handling + * of parameter-specific logic, such as invoking a help command or performing + * business logic with the values parsed from the command-line arguments. + */ + private Consumer> callback; + + /** + * Indicates whether the parameter is designated as the help command. + *

+ * When set to {@code true}, this parameter is treated as the special help command + * within the command-line parser. A parameter marked as the help command typically + * provides users with information about available options or detailed descriptions + * of specific commands when invoked. If this flag is enabled, a custom callback + * method for displaying help context is automatically associated with the parameter. + */ + private boolean isHelpCommand; + + /** + * Indicates whether the parameter is designated as the default parameter. + *

+ * The default parameter is a special type of parameter that can accept arguments + * without an explicit prefix or identifier. It is used when a provided command-line + * argument does not match any defined parameter and does not start with a special + * character (e.g., '-') typically used to denote named parameters. + *

+ * If this field is set to {@code true}, the parameter is treated as the default + * parameter. Only one parameter can be assigned this role within the parser. + * Attempting to assign multiple default parameters or a default parameter without + * accepting values (both `minNumberValues` and `maxNumberValues` set to 0) will + * result in an exception during configuration. + *

+ * This property is utilized during the parsing process to determine whether an + * unmatched argument should be handled as a default parameter value, simplifying + * the handling of positional arguments or other unnamed input data. + */ + private boolean isDefaultParameter; + + /** + * A list of alias names associated with a parameter. + *

+ * This variable holds alternative names that can be used + * to reference the parameter in command-line input. Each alias + * functions as an equivalent to the primary parameter name. + * Aliases are case-insensitive when used within the command-line parser. + *

+ * The aliases associated with a parameter allow greater flexibility + * and user convenience when specifying parameters during command-line execution. + */ + @Singular("alias") + private List aliasList; + /** * Represents a command-line parameter definition within the application. - * + *

* This class encapsulates the metadata and configuration of a command-line parameter, * including its name, aliases, descriptions, value constraints, and behavior. Instances * of this class are used to define and manage the parameters that the `Parser` class * recognizes and processes. - * + *

* A parameter can be configured as a default parameter or as a help command. The default * parameter serves as a catch-all for unmatched command-line inputs, while the help * command provides usage information for users. @@ -41,16 +168,16 @@ public class Parameter { /** * Constructs a new Parameter with the given attributes. * - * @param name The name of the parameter. - * @param minNumberValues The minimum number of values allowed for this parameter. - * @param maxNumberValues The maximum number of values allowed for this parameter. - * @param multipleEntries Indicates whether multiple entries are allowed for this parameter. - * @param shortDescription A brief description of the parameter. - * @param longDescription A detailed description of the parameter. - * @param callback A consumer function that processes a list of values associated with this parameter. - * @param isHelpCommand Indicates whether this parameter represents a help command. + * @param name The name of the parameter. + * @param minNumberValues The minimum number of values allowed for this parameter. + * @param maxNumberValues The maximum number of values allowed for this parameter. + * @param multipleEntries Indicates whether multiple entries are allowed for this parameter. + * @param shortDescription A brief description of the parameter. + * @param longDescription A detailed description of the parameter. + * @param callback A consumer function that processes a list of values associated with this parameter. + * @param isHelpCommand Indicates whether this parameter represents a help command. * @param isDefaultParameter Indicates whether this parameter is the default parameter. - * @param aliasList A list of aliases for this parameter. + * @param aliasList A list of aliases for this parameter. */ public Parameter(String name, int minNumberValues, int maxNumberValues, boolean multipleEntries, String shortDescription, String longDescription, Consumer> callback, boolean isHelpCommand, boolean isDefaultParameter, List aliasList) { this.name = name; @@ -64,131 +191,4 @@ public class Parameter { this.isDefaultParameter = isDefaultParameter; this.aliasList = aliasList; } - - /** - * The `name` variable represents the primary identifier for a parameter. - * This string is used to uniquely identify a command-line parameter when parsing - * arguments. It serves as the key for registering and retrieving parameters in a - * command-line parser. - * - * The value of `name` is case-insensitive and can be used alongside aliases to - * recognize and process parameters provided in the command-line input. - */ - private String name; - - /** - * Specifies the minimum number of values required for this parameter. - * - * This variable enforces a constraint on the number of arguments that must - * be provided for the parameter during command-line parsing. If the number of - * provided arguments is less than this value, an exception will be thrown during parsing. - * - * It is primarily used in validation logic within the command-line parser - * to ensure the required input is received for proper processing of the parameter. - */ - private int minNumberValues; - - /** - * Specifies the maximum number of values that the corresponding parameter can accept. - * - * This field is used to validate and enforce constraints during command-line parsing. - * If more values than specified are provided for a parameter, the parser throws an exception - * to indicate a violation of this constraint. - * - * A value of 0 implies that the parameter does not support any values, while a positive - * value indicates the exact maximum limit of acceptable values. - */ - private int maxNumberValues; - - /** - * Indicates whether the parameter allows multiple entries. - * - * If set to {@code true}, the parameter can be specified multiple times - * on the command-line. This allows the association of multiple values - * or options with the same parameter name. - * - * If set to {@code false}, the parameter can be specified only once - * during command-line parsing. - */ - private boolean multipleEntries; - - /** - * A concise, human-readable description of the parameter's purpose and functionality. - * - * This description provides a brief summary to help users understand the - * essential role of the parameter within the command-line parser. It is typically - * displayed in usage instructions, help messages, or command summaries. - */ - private String shortDescription; - - /** - * A detailed, extended description of the parameter's purpose and usage. - * - * This description provides deeper context about what the parameter represents, - * how it fits into the overall command-line application, and any nuances - * associated with its use. It is displayed when help or additional documentation - * for a specific parameter is requested. - */ - private String longDescription; - - /** - * A callback function that processes a list of string arguments for a specific parameter. - * The callback is invoked during command-line parsing when a parameter is recognized, - * passing the associated values of the parameter for further processing. - * - * The provided {@link Consumer} implementation defines the logic to - * handle or validate the values supplied for a command-line parameter. The values - * passed are determined based on the parameter's configuration (e.g., minimum and - * maximum number of associated values). - * - * This field is typically set for the `Parameter` class to enable custom handling - * of parameter-specific logic, such as invoking a help command or performing - * business logic with the values parsed from the command-line arguments. - */ - private Consumer> callback; - - /** - * Indicates whether the parameter is designated as the help command. - * - * When set to {@code true}, this parameter is treated as the special help command - * within the command-line parser. A parameter marked as the help command typically - * provides users with information about available options or detailed descriptions - * of specific commands when invoked. If this flag is enabled, a custom callback - * method for displaying help context is automatically associated with the parameter. - */ - private boolean isHelpCommand; - - /** - * Indicates whether the parameter is designated as the default parameter. - * - * The default parameter is a special type of parameter that can accept arguments - * without an explicit prefix or identifier. It is used when a provided command-line - * argument does not match any defined parameter and does not start with a special - * character (e.g., '-') typically used to denote named parameters. - * - * If this field is set to {@code true}, the parameter is treated as the default - * parameter. Only one parameter can be assigned this role within the parser. - * Attempting to assign multiple default parameters or a default parameter without - * accepting values (both `minNumberValues` and `maxNumberValues` set to 0) will - * result in an exception during configuration. - * - * This property is utilized during the parsing process to determine whether an - * unmatched argument should be handled as a default parameter value, simplifying - * the handling of positional arguments or other unnamed input data. - */ - private boolean isDefaultParameter; - - /** - * A list of alias names associated with a parameter. - * - * This variable holds alternative names that can be used - * to reference the parameter in command-line input. Each alias - * functions as an equivalent to the primary parameter name. - * Aliases are case-insensitive when used within the command-line parser. - * - * The aliases associated with a parameter allow greater flexibility - * and user convenience when specifying parameters during command-line execution. - */ - @Singular("alias") - private List aliasList; } diff --git a/core/src/main/java/de/neitzel/core/commandline/Parser.java b/core/src/main/java/de/neitzel/core/commandline/Parser.java index f6e7728..63506a7 100644 --- a/core/src/main/java/de/neitzel/core/commandline/Parser.java +++ b/core/src/main/java/de/neitzel/core/commandline/Parser.java @@ -2,7 +2,11 @@ package de.neitzel.core.commandline; import lombok.extern.slf4j.Slf4j; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * The Parser class is responsible for parsing and handling command-line arguments. @@ -15,32 +19,32 @@ public class Parser { /** * A map to store parameters where the key is a string representing * the parameter name and the value is the corresponding {@link Parameter} object. - * + *

* This map serves as a registry for defining, organizing, and accessing * command-line parameters. Each entry holds a parameter's metadata and * its associated configuration to facilitate effective command-line parsing. - * + *

* Key considerations: * - The key represents the primary name of the parameter. * - The value, encapsulated as a {@link Parameter} object, includes - * details such as descriptions, value constraints, aliases, and processing logic. + * details such as descriptions, value constraints, aliases, and processing logic. */ private Map parameters = new HashMap<>(); /** * The `defaultParameter` variable represents the default command-line parameter for a parser. - * + *

* This parameter is used to capture arguments that do not explicitly match any named parameter * or alias. It acts as a catch-all for unnamed command-line input, often simplifying the handling * of positional arguments or other free-form input provided by the user. - * + *

* It is essential to note: * - Only one parameter can be designated as the default parameter in a command-line parser. * - The parameter must allow values to be processed (e.g., its `minNumberValues` or `maxNumberValues` - * should not disallow input). + * should not disallow input). * - This parameter is automatically invoked if an input does not match any explicitly named - * parameter or alias in the parser configuration. - * + * parameter or alias in the parser configuration. + *

* When set to `null`, the parser does not handle unmatched arguments, and unrecognized inputs * may result in an error or exception, depending on the parser's implementation. */ @@ -48,12 +52,12 @@ public class Parser { /** * Constructs a new instance of the `Parser` class. - * + *

* The `Parser` class is responsible for parsing and processing * command-line arguments. It interprets input data based on defined * parameters and provides structured access to arguments, enabling * streamlined application configuration and execution. - * + *

* This constructor initializes the parser without any predefined * configuration or parameters. Users can define parameters, * add handlers, and parse command-line arguments using available @@ -71,7 +75,6 @@ public class Parser { * and other metadata such as whether it is a help command or default parameter. * The parameter must fulfill specific constraints if defined as the default * parameter (e.g., accepting values). - * * @throws IllegalArgumentException if the parameter is defined as a default parameter and * does not accept values (both minNumberValues and maxNumberValues * are set to 0). @@ -81,7 +84,7 @@ public class Parser { parameters.put(parameter.getName().toLowerCase(), parameter); // Add for all aliases - for (String alias: parameter.getAliasList()) { + for (String alias : parameter.getAliasList()) { parameters.put(alias.toLowerCase(), parameter); } @@ -98,22 +101,39 @@ public class Parser { } /** - * Checks whether a given parameter string matches a valid parameter within the defined constraints. + * Handles the help command when invoked in the command-line interface, providing information about available parameters. + * If no arguments are provided, it lists all possible parameters and their short descriptions. + * If specific arguments are supplied, it provides the detailed description of the corresponding parameter. + * In case an unknown parameter is specified, it indicates so to the user. * - * @param param the parameter string to be checked. This can either be a key defined in the `parameters` map - * or a potential default parameter if it does not start with a dash ("-"). - * @return {@code true} if the parameter is a valid entry in the `parameters` map or matches the default parameter; - * {@code false} otherwise, including when the parameter starts with a dash ("-"). + * @param arguments a list of strings representing the user-provided arguments. If empty or {@code null}, + * the method lists all available parameters with their short descriptions. If a parameter name + * is provided in the list, its detailed information is displayed. If an unrecognized parameter + * is provided, a corresponding message is shown. */ - protected boolean isParameter(final String param) { - if (parameters.containsKey(param)) return true; - if (param.startsWith("-")) return false; - return defaultParameter != null; + public void helpCommandCallback(final List arguments) { + if (arguments == null || arguments.size() == 0) { + System.out.println("Moegliche Parameter der Applikation:"); + parameters.values().stream() + .distinct() + .sorted(Comparator.comparing(Parameter::getName)) + .forEach(p -> System.out.println(p.getShortDescription())); + } else { + Parameter parameter = null; + if (parameters.containsKey(arguments.get(0))) parameter = parameters.get(arguments.get(0)); + if (parameters.containsKey("-" + arguments.get(0))) parameter = parameters.get("-" + arguments.get(0)); + + if (parameter == null) { + System.out.println("Unbekannter Parameter: " + arguments.get(0)); + } else { + System.out.println(parameter.getLongDescription()); + } + } } /** * Parses an array of command-line arguments and processes them as defined by the application's parameters. - * + *

* The method iteratively checks each argument in the provided array, validates it against * the registered parameters, and invokes the corresponding processing callback if applicable. * Unrecognized parameters or missing required values will result in an {@code IllegalArgumentException}. @@ -151,6 +171,20 @@ public class Parser { } } + /** + * Checks whether a given parameter string matches a valid parameter within the defined constraints. + * + * @param param the parameter string to be checked. This can either be a key defined in the `parameters` map + * or a potential default parameter if it does not start with a dash ("-"). + * @return {@code true} if the parameter is a valid entry in the `parameters` map or matches the default parameter; + * {@code false} otherwise, including when the parameter starts with a dash ("-"). + */ + protected boolean isParameter(final String param) { + if (parameters.containsKey(param)) return true; + if (param.startsWith("-")) return false; + return defaultParameter != null; + } + /** * Retrieves a list of options by consuming arguments from the provided {@link ArgumentProvider} * within the range specified by the minimum and maximum values. @@ -163,8 +197,8 @@ public class Parser { * than `min`, it will be adjusted to match `min`. Only up to `max` * arguments will be added to the result. * @return A list of argument strings, containing up to `max` elements and at least `min` - * elements if sufficient arguments are available. The list will not include - * arguments already recognized in the `parameters` map. + * elements if sufficient arguments are available. The list will not include + * arguments already recognized in the `parameters` map. */ private List getOptions(ArgumentProvider provider, int min, int max) { if (max < min) max = min; @@ -182,35 +216,4 @@ public class Parser { return result; } - - /** - * Handles the help command when invoked in the command-line interface, providing information about available parameters. - * If no arguments are provided, it lists all possible parameters and their short descriptions. - * If specific arguments are supplied, it provides the detailed description of the corresponding parameter. - * In case an unknown parameter is specified, it indicates so to the user. - * - * @param arguments a list of strings representing the user-provided arguments. If empty or {@code null}, - * the method lists all available parameters with their short descriptions. If a parameter name - * is provided in the list, its detailed information is displayed. If an unrecognized parameter - * is provided, a corresponding message is shown. - */ - public void helpCommandCallback(final List arguments) { - if (arguments == null || arguments.size() == 0) { - System.out.println("Moegliche Parameter der Applikation:"); - parameters.values().stream() - .distinct() - .sorted(Comparator.comparing(Parameter::getName)) - .forEach(p -> System.out.println(p.getShortDescription() )); - } else { - Parameter parameter = null; - if (parameters.containsKey(arguments.get(0))) parameter = parameters.get(arguments.get(0)); - if (parameters.containsKey("-" + arguments.get(0))) parameter = parameters.get("-" + arguments.get(0)); - - if (parameter == null) { - System.out.println("Unbekannter Parameter: " + arguments.get(0)); - } else { - System.out.println(parameter.getLongDescription()); - } - } - } } diff --git a/core/src/main/java/de/neitzel/core/image/ImageScaler.java b/core/src/main/java/de/neitzel/core/image/ImageScaler.java index 19ca807..bc357f9 100644 --- a/core/src/main/java/de/neitzel/core/image/ImageScaler.java +++ b/core/src/main/java/de/neitzel/core/image/ImageScaler.java @@ -17,6 +17,19 @@ import java.io.InputStream; @Slf4j public class ImageScaler { + /** + * Specifies the target image format for scaling operations. + *

+ * This variable defines the file format that will be used when writing + * or encoding the scaled image. The format must be compatible with + * Java's ImageIO framework (e.g., "png", "jpg", "bmp"). + *

+ * In this case, the target format is set to "png", allowing images + * to be scaled and saved or returned as PNG files. It ensures + * consistent output format across the image scaling methods in the class. + */ + private static String TARGET_FORMAT = "png"; + /** * Private constructor to prevent instantiation of this utility class. */ @@ -24,59 +37,17 @@ public class ImageScaler { throw new UnsupportedOperationException("Utility class cannot be instantiated"); } - /** - * Specifies the target image format for scaling operations. - * - * This variable defines the file format that will be used when writing - * or encoding the scaled image. The format must be compatible with - * Java's ImageIO framework (e.g., "png", "jpg", "bmp"). - * - * In this case, the target format is set to "png", allowing images - * to be scaled and saved or returned as PNG files. It ensures - * consistent output format across the image scaling methods in the class. - */ - private static String TARGET_FORMAT="png"; - - /** - * Creates a scaled image from the given byte array representation and returns it as a byte array. - * - * If enforceSize is set to false, the given dimensions are used as maximum values for scaling. - * The resulting image may retain its aspect ratio and be smaller than the specified dimensions. - * If enforceSize is true, the resulting image will match the exact dimensions, potentially adding - * transparent areas on the top/bottom or right/left sides to maintain the original aspect ratio. - * - * @param originalImageBytes The byte array representing the original image. - * @param width The (maximum) width of the target image. - * @param height The (maximum) height of the target image. - * @param enforceSize A flag indicating whether the resulting image should strictly adhere to specified dimensions. - * If false, the image will retain its aspect ratio without empty borders. - * @return A byte array representing the scaled image, or null if the operation failed or the input was invalid. - */ - public static byte[] createScaledImage(final byte[] originalImageBytes, final int width, final int height, final boolean enforceSize) { - // Validation - if (originalImageBytes == null) return null; - if (originalImageBytes.length==0) return null; - - try { - // Create the image from a byte array. - BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(originalImageBytes)); - return createScaledImage(originalImage, width, height, enforceSize); - } catch (Exception ex) { - return null; - } - } - /** * Scales an image provided as a byte array to the specified dimensions and returns an InputStream of the scaled image. - * + *

* The scaling behavior is determined by the enforceSize parameter: * - If enforceSize is false, the provided dimensions are treated as maximum values, maintaining the original aspect ratio. * - If enforceSize is true, the resulting image will match the exact dimensions, potentially with transparent borders to keep the original aspect ratio. * * @param originalImageBytes The byte array representing the original image. - * @param width The (maximum) width of the target scaled image. - * @param height The (maximum) height of the target scaled image. - * @param enforceSize A flag indicating whether to enforce the exact scaled dimensions. If false, the resulting image retains its aspect ratio. + * @param width The (maximum) width of the target scaled image. + * @param height The (maximum) height of the target scaled image. + * @param enforceSize A flag indicating whether to enforce the exact scaled dimensions. If false, the resulting image retains its aspect ratio. * @return An InputStream representing the scaled image, or null if the operation fails or the input image is invalid. */ public static InputStream scaledImage(final byte[] originalImageBytes, final int width, final int height, final boolean enforceSize) { @@ -91,20 +62,49 @@ public class ImageScaler { } /** - * Creates a scaled version of the given {@link BufferedImage} and returns it as a byte array. + * Creates a scaled image from the given byte array representation and returns it as a byte array. + *

+ * If enforceSize is set to false, the given dimensions are used as maximum values for scaling. + * The resulting image may retain its aspect ratio and be smaller than the specified dimensions. + * If enforceSize is true, the resulting image will match the exact dimensions, potentially adding + * transparent areas on the top/bottom or right/left sides to maintain the original aspect ratio. * + * @param originalImageBytes The byte array representing the original image. + * @param width The (maximum) width of the target image. + * @param height The (maximum) height of the target image. + * @param enforceSize A flag indicating whether the resulting image should strictly adhere to specified dimensions. + * If false, the image will retain its aspect ratio without empty borders. + * @return A byte array representing the scaled image, or null if the operation failed or the input was invalid. + */ + public static byte[] createScaledImage(final byte[] originalImageBytes, final int width, final int height, final boolean enforceSize) { + // Validation + if (originalImageBytes == null) return null; + if (originalImageBytes.length == 0) return null; + + try { + // Create the image from a byte array. + BufferedImage originalImage = ImageIO.read(new ByteArrayInputStream(originalImageBytes)); + return createScaledImage(originalImage, width, height, enforceSize); + } catch (Exception ex) { + return null; + } + } + + /** + * Creates a scaled version of the given {@link BufferedImage} and returns it as a byte array. + *

* The scaling behavior is determined by the enforceSize parameter: * - If enforceSize is false, the provided dimensions are treated as maximum values, and the image - * will maintain its original aspect ratio. The resulting image may be smaller than the specified - * dimensions. + * will maintain its original aspect ratio. The resulting image may be smaller than the specified + * dimensions. * - If enforceSize is true, the resulting image will match the exact specified dimensions, potentially - * adding transparent padding to fit the aspect ratio. + * adding transparent padding to fit the aspect ratio. * * @param originalImage The original image to be scaled. Must not be null. - * @param width The specified (maximum) width of the scaled image. - * @param height The specified (maximum) height of the scaled image. - * @param enforceSize A flag indicating whether the scaled image should strictly conform to the specified - * dimensions. If true, the image may include transparent areas to maintain the aspect ratio. + * @param width The specified (maximum) width of the scaled image. + * @param height The specified (maximum) height of the scaled image. + * @param enforceSize A flag indicating whether the scaled image should strictly conform to the specified + * dimensions. If true, the image may include transparent areas to maintain the aspect ratio. * @return A byte array representing the scaled image, or null if the scaling operation fails or the input image is invalid. */ protected static byte[] createScaledImage(final BufferedImage originalImage, final int width, final int height, final boolean enforceSize) { diff --git a/core/src/main/java/de/neitzel/core/inject/ApplicationContext.java b/core/src/main/java/de/neitzel/core/inject/ApplicationContext.java index aca45d2..783b57f 100644 --- a/core/src/main/java/de/neitzel/core/inject/ApplicationContext.java +++ b/core/src/main/java/de/neitzel/core/inject/ApplicationContext.java @@ -10,7 +10,7 @@ import java.util.stream.Stream; /** * Represents the context of the application and serves as the foundation of a dependency * injection framework. - * + *

* The {@code ApplicationContext} is responsible for scanning, instantiating, and managing * the lifecycle of components. Components are identified through the specified base package * (or derived from a configuration class) and instantiated based on their dependency @@ -52,17 +52,17 @@ public class ApplicationContext { /** * Retrieves an instance of the specified component type from the application context. - * + *

* This method uses dependency injection to construct the component if it is not already * a singleton instance. The component's type and scope are determined by the framework, * and the appropriate initialization and lifecycle management are performed. * - * @param the type of the component to retrieve + * @param the type of the component to retrieve * @param type the {@code Class} object representing the type of the component * @return an instance of the requested component type * @throws IllegalArgumentException if no component is found for the specified type - * @throws IllegalStateException if no suitable constructor is found for the component - * @throws RuntimeException if any error occurs during instantiation + * @throws IllegalStateException if no suitable constructor is found for the component + * @throws RuntimeException if any error occurs during instantiation */ @SuppressWarnings("unchecked") public T getComponent(Class type) { @@ -85,7 +85,7 @@ public class ApplicationContext { Class[] paramTypes = constructor.getParameterTypes(); Object[] parameters = new Object[paramTypes.length]; for (int i = 0; i < paramTypes.length; i++) { - parameters[i] = getComponent(paramTypes[i]); + parameters[i] = getComponent(paramTypes[i]); } instance = constructor.newInstance(parameters); if (scope == Scope.SINGLETON) { @@ -103,12 +103,12 @@ public class ApplicationContext { /** * Determines if a given constructor can be instantiated using the provided parameter map. - * + *

* The method evaluates whether every parameter type required by the constructor * is available in the given parameter map. If all parameter types are present, * the constructor is considered instantiable. * - * @param constructor the constructor to check for instantiation feasibility + * @param constructor the constructor to check for instantiation feasibility * @param parameterMap a map containing available parameter types and their associated component data * @return true if all parameter types required by the constructor are contained in the parameter map, false otherwise */ @@ -118,14 +118,14 @@ public class ApplicationContext { /** * Registers a singleton instance of a specific type into the application context. - * + *

* This method allows manual addition of singleton components to the context by * providing a concrete instance of the required type. If the type is already mapped * to a different instance or type within the context, an {@link IllegalStateException} * is thrown to prevent replacement of an existing singleton. * - * @param the type of the component to register - * @param type the class type of the component being added + * @param the type of the component to register + * @param type the class type of the component being added * @param instance the singleton instance of the component to register * @throws IllegalStateException if the type is already registered with a different instance */ diff --git a/core/src/main/java/de/neitzel/core/inject/ComponentData.java b/core/src/main/java/de/neitzel/core/inject/ComponentData.java index 742227e..a206a17 100644 --- a/core/src/main/java/de/neitzel/core/inject/ComponentData.java +++ b/core/src/main/java/de/neitzel/core/inject/ComponentData.java @@ -4,7 +4,7 @@ import lombok.Getter; /** * Represents a component in a dependency injection framework. - * + *

* A component is a unit of functionality that is managed by the framework, allowing * for controlled instantiation and lifecycle management. The component is associated * with a specific type and a scope. The scope determines whether the component is @@ -15,7 +15,7 @@ public class ComponentData { /** * Represents the type of the component being managed by the dependency injection framework. - * + *

* This variable holds the class object corresponding to the specific type of the component. * It is used to identify and instantiate the component during the dependency injection process. * The type is immutable and is specified when the component is created. @@ -24,10 +24,10 @@ public class ComponentData { /** * Defines the lifecycle and instantiation rules for the associated component. - * + *

* The {@code Scope} determines whether the component is created as a singleton * (a single shared instance) or as a prototype (a new instance for each request). - * + *

* This variable is immutable and represents the specific {@code Scope} assigned * to the component, influencing its behavior within the dependency injection framework. */ @@ -35,7 +35,7 @@ public class ComponentData { /** * Stores the instantiated object associated with the component. - * + *

* This field holds the actual instance of the component's type within the dependency * injection framework. For components with a {@code SINGLETON} scope, this field is * set only once and shared across the entire application. For components with a @@ -47,7 +47,7 @@ public class ComponentData { /** * Constructs a new Component instance with the specified type and scope. * - * @param type the class type of the component + * @param type the class type of the component * @param scope the scope of the component, which determines its lifecycle */ public ComponentData(Class type, Scope scope) { @@ -57,10 +57,10 @@ public class ComponentData { /** * Constructs a new ComponentData instance with the specified type and an initial instance. - * + *

* This can be used to add Singletons manually without scanning for them. * - * @param type the class type of the component + * @param type the class type of the component * @param instance the initial instance of the component */ public ComponentData(Class type, Object instance) { diff --git a/core/src/main/java/de/neitzel/core/inject/ComponentScanner.java b/core/src/main/java/de/neitzel/core/inject/ComponentScanner.java index 244b443..7e75593 100644 --- a/core/src/main/java/de/neitzel/core/inject/ComponentScanner.java +++ b/core/src/main/java/de/neitzel/core/inject/ComponentScanner.java @@ -5,7 +5,13 @@ import de.neitzel.core.inject.annotation.Inject; import org.reflections.Reflections; import java.lang.reflect.Constructor; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; /** @@ -21,13 +27,13 @@ public class ComponentScanner { * FXML-compatible components detected during the scanning process. * These components are used as part of the dependency injection mechanism * within the {@code InjectableComponentScanner}. - * + *

* The {@code fxmlComponents} set is populated during the component scanning * phase by identifying all classes within a specified package hierarchy * annotated with the {@code @Component} annotation. These classes serve * as the primary source for further analysis, resolution, and instantiation * in the scanning workflow. - * + *

* This field is immutable, ensuring thread safety and consistent state * throughout the lifetime of the {@code InjectableComponentScanner}. */ @@ -35,12 +41,12 @@ public class ComponentScanner { /** * A set of component types that are not uniquely associated with a single implementation. - * + *

* This collection is populated during the analysis of discovered components to identify * types that have multiple implementations, preventing them from being uniquely resolved. * For example, if multiple components implement the same interface, that interface will be * added to this set. - * + *

* It is primarily used during the component registration process to avoid ambiguities * in the dependency injection system, ensuring that only resolvable, uniquely identifiable * components can be instantiated and injected. @@ -52,13 +58,13 @@ public class ComponentScanner { * The key represents a super type (interface or abstract class), and the value * is the specific implementation or subclass that is uniquely identified among * the scanned components. - * + *

* This map is populated during the component analysis process. For each super type * in the scanned components, if exactly one implementation is found, it is * considered unique and added to this mapping. In case multiple implementations * exist for a given super type, it is excluded from this map and classified as * a non-unique type. - * + *

* This mapping is utilized for resolving dependencies and determining which components * can be instantiated based on unique type information. */ @@ -70,7 +76,7 @@ public class ComponentScanner { * that can be instantiated. The entries are resolved through the scanning and analysis * of available component types, ensuring that only components with resolvable * dependencies are included. - * + *

* This field is part of the dependency injection process, where components annotated * with {@code @Component} or similar annotations are scanned, analyzed, and registered. * The resolution process checks if a component can be instantiated based on its @@ -81,11 +87,11 @@ public class ComponentScanner { /** * A list of error messages encountered during the scanning and analysis * of components in the dependency injection process. - * + *

* This list is populated when components cannot be resolved due to issues * such as multiple implementations of a superclass or interface, * unmet construction requirements, or unresolved dependencies. - * + *

* Errors added to this list provide detailed descriptions of the specific * issues that prevent certain components from being instantiated correctly. */ @@ -117,19 +123,19 @@ public class ComponentScanner { /** * Analyzes component types within the injected components and classifies them based on their * inheritance hierarchy and relationships. - * + *

* This method performs the following operations: * 1. Maps each component to all of its superclasses and interfaces. * 2. Identifies which superclasses or interfaces have multiple implementing components. * 3. Populates: - * - A list of superclasses or interfaces that are not uniquely linked to a single component. - * - A map where unique superclasses or interfaces are associated with a specific implementing component. - * + * - A list of superclasses or interfaces that are not uniquely linked to a single component. + * - A map where unique superclasses or interfaces are associated with a specific implementing component. + *

* The mappings are built using the following data structures: * - A map from superclasses/interfaces to the list of components that implement or extend them. * - A list of non-unique types where multiple components exist for the same superclass or interface. * - A map of unique superclasses/interfaces to their corresponding component. - * + *

* This method is a key part of the component scanning and resolution process, facilitating * the identification of potential instantiation ambiguities or conflicts. */ @@ -160,22 +166,22 @@ public class ComponentScanner { * Resolves and identifies instantiable components from a set of scanned components. * This process determines which components can be instantiated based on their dependencies * and class relationships, while tracking unresolved types and potential conflicts. - * + *

* The resolution process involves: * 1. Iteratively determining which components can be instantiated using the known types - * map. A component is resolvable if its dependencies can be satisfied by the current - * set of known types. + * map. A component is resolvable if its dependencies can be satisfied by the current + * set of known types. * 2. Registering resolvable components and their superclasses/interfaces into the known - * types map for future iterations. + * types map for future iterations. * 3. Removing successfully resolved components from the unresolved set. * 4. Repeating the process until no further components can be resolved in a given iteration. - * + *

* At the end of the resolution process: * - Resolvable components are added to the `instantiableComponents` map, which maps types - * to their corresponding instantiable implementations. + * to their corresponding instantiable implementations. * - Unresolved components are identified, and error details are collected to highlight - * dependencies or conflicts preventing their instantiation. - * + * dependencies or conflicts preventing their instantiation. + *

* If errors are encountered due to unresolved components, they are logged for further analysis. */ private void resolveInstantiableComponents() { @@ -208,21 +214,22 @@ public class ComponentScanner { } /** - * Registers a component and its superclasses or interfaces in the provided map of known types. - * This method ensures that the component and its inheritance hierarchy are associated with the - * component's data unless the supertype is marked as non-unique. + * Retrieves all superclasses and interfaces of the specified class, excluding the {@code Object} class. * - * @param component the {@code ComponentData} instance representing the component to be registered - * @param knownTypes the map where component types and their data are stored + * @param clazz the class for which to retrieve all superclasses and interfaces + * @return a set of all superclasses and interfaces implemented by the specified class */ - private void registerComponentWithSuperTypes(ComponentData component, Map, ComponentData> knownTypes) { - knownTypes.put(component.getType(), component); + private Set> getAllSuperTypes(Class clazz) { + Set> result = new HashSet<>(); + Class superClass = clazz.getSuperclass(); - for (Class superType : getAllSuperTypes(component.getType())) { - if (!notUniqueTypes.contains(superType)) { - knownTypes.put(superType, component); - } + while (superClass != null && superClass != Object.class) { + result.add(superClass); + superClass = superClass.getSuperclass(); } + + result.addAll(Arrays.asList(clazz.getInterfaces())); + return result; } /** @@ -232,7 +239,7 @@ public class ComponentScanner { * Additionally, all fields annotated with {@code @Inject} must have their types present in the * known types set. * - * @param component the class to check for instantiability + * @param component the class to check for instantiability * @param knownTypes the set of currently known types that can be used to satisfy dependencies * @return {@code true} if the component can be instantiated; {@code false} otherwise */ @@ -260,6 +267,24 @@ public class ComponentScanner { return true; } + /** + * Registers a component and its superclasses or interfaces in the provided map of known types. + * This method ensures that the component and its inheritance hierarchy are associated with the + * component's data unless the supertype is marked as non-unique. + * + * @param component the {@code ComponentData} instance representing the component to be registered + * @param knownTypes the map where component types and their data are stored + */ + private void registerComponentWithSuperTypes(ComponentData component, Map, ComponentData> knownTypes) { + knownTypes.put(component.getType(), component); + + for (Class superType : getAllSuperTypes(component.getType())) { + if (!notUniqueTypes.contains(superType)) { + knownTypes.put(superType, component); + } + } + } + /** * Collects the instantiation errors for a set of unresolved classes and appends * detailed error messages to the internal error list. This method analyzes unresolved @@ -304,7 +329,7 @@ public class ComponentScanner { * * @param component the class for which conflicting types need to be identified. * @return a comma-separated string of fully qualified names of conflicting parameter types, - * or an empty string if no conflicts are found. + * or an empty string if no conflicts are found. */ private String getConflictingTypes(Class component) { return Arrays.stream(component.getConstructors()) @@ -314,30 +339,11 @@ public class ComponentScanner { .collect(Collectors.joining(", ")); } - /** - * Retrieves all superclasses and interfaces of the specified class, excluding the {@code Object} class. - * - * @param clazz the class for which to retrieve all superclasses and interfaces - * @return a set of all superclasses and interfaces implemented by the specified class - */ - private Set> getAllSuperTypes(Class clazz) { - Set> result = new HashSet<>(); - Class superClass = clazz.getSuperclass(); - - while (superClass != null && superClass != Object.class) { - result.add(superClass); - superClass = superClass.getSuperclass(); - } - - result.addAll(Arrays.asList(clazz.getInterfaces())); - return result; - } - /** * Retrieves a map of classes representing component types to their corresponding instantiable implementations. * * @return A map where the key is a class type and the value is the corresponding class implementation - * that can be instantiated. + * that can be instantiated. */ public Map, ComponentData> getInstantiableComponents() { return instantiableComponents; @@ -349,7 +355,7 @@ public class ComponentScanner { * component scanning and analysis process. * * @return a set of classes representing the types that have multiple - * implementations and cannot be resolved uniquely + * implementations and cannot be resolved uniquely */ public Set> getNotUniqueTypes() { return notUniqueTypes; @@ -361,7 +367,7 @@ public class ComponentScanner { * implementation, ensuring no ambiguity in resolution. * * @return a map where the keys are types (e.g., interfaces or superclasses) - * and the values are their unique component implementations. + * and the values are their unique component implementations. */ public Map, Class> getUniqueTypeToComponent() { return uniqueTypeToComponent; diff --git a/core/src/main/java/de/neitzel/core/inject/annotation/Component.java b/core/src/main/java/de/neitzel/core/inject/annotation/Component.java index 4351ad9..7cb0c80 100644 --- a/core/src/main/java/de/neitzel/core/inject/annotation/Component.java +++ b/core/src/main/java/de/neitzel/core/inject/annotation/Component.java @@ -11,14 +11,14 @@ import java.lang.annotation.Target; * Indicates that an annotated class is a "component" within a dependency injection framework. * Classes annotated with {@code @Component} are recognized during the component scanning process * as candidates for instantiation and management by the dependency injection framework. - * + *

* This annotation is typically used on classes that represent application-specific components, * such as service implementations, controllers, or other objects intended to be instantiated * and injected into other components during runtime. - * + *

* The annotation must be placed at the type level, and it is retained at runtime * to allow for reflection-based scanning of classes within specified packages. - * + *

* Usage of this annotation assumes that there exists a component scanning mechanism * that processes annotated classes and identifies their roles, dependencies, and hierarchy * within the application's structure. diff --git a/core/src/main/java/de/neitzel/core/inject/annotation/Config.java b/core/src/main/java/de/neitzel/core/inject/annotation/Config.java index cac196d..50d8b14 100644 --- a/core/src/main/java/de/neitzel/core/inject/annotation/Config.java +++ b/core/src/main/java/de/neitzel/core/inject/annotation/Config.java @@ -10,17 +10,17 @@ import java.lang.annotation.Target; * injection framework. Classes annotated with {@code @Config} are used as markers * for defining settings and application-specific configurations required by the * dependency injection mechanism. - * + *

* Typically, configuration classes provide metadata required for setting up the * framework, such as specifying the base package to scan for components. - * + *

* This annotation must be applied at the type level and is retained at runtime to * facilitate reflection-based processing. It is intended to serve as a declarative * representation of configuration options for the dependency injection container. - * + *

* Attributes: * - {@code basePackage}: Specifies the package name where the framework should scan - * for classes annotated with dependency injection annotations such as {@code @Component}. + * for classes annotated with dependency injection annotations such as {@code @Component}. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @@ -31,7 +31,7 @@ public @interface Config { * can be scanned and identified as candidates for dependency injection. * * @return the base package name as a string; returns an empty string by default - * if no specific package is defined. + * if no specific package is defined. */ String basePackage() default ""; } diff --git a/core/src/main/java/de/neitzel/core/inject/annotation/Inject.java b/core/src/main/java/de/neitzel/core/inject/annotation/Inject.java index bf2b703..4b18d29 100644 --- a/core/src/main/java/de/neitzel/core/inject/annotation/Inject.java +++ b/core/src/main/java/de/neitzel/core/inject/annotation/Inject.java @@ -10,10 +10,10 @@ import java.lang.annotation.Target; * a dependency injection framework. Fields annotated with {@code @Inject} * are automatically populated with the required component instance during runtime, * typically by the dependency injection container. - * + *

* This annotation must be applied at the field level and is retained at runtime * to enable reflection-based identification and assignment of dependencies. - * + *

* The framework's dependency resolution mechanism identifies the appropriate * instance to inject based on the field's type or custom configuration, * ensuring loose coupling and easier testability. diff --git a/core/src/main/java/de/neitzel/core/io/ConvertedEncodingFileReader.java b/core/src/main/java/de/neitzel/core/io/ConvertedEncodingFileReader.java index ce6205c..9e2f0fb 100644 --- a/core/src/main/java/de/neitzel/core/io/ConvertedEncodingFileReader.java +++ b/core/src/main/java/de/neitzel/core/io/ConvertedEncodingFileReader.java @@ -2,7 +2,11 @@ package de.neitzel.core.io; import lombok.extern.slf4j.Slf4j; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; diff --git a/core/src/main/java/de/neitzel/core/io/FileUtils.java b/core/src/main/java/de/neitzel/core/io/FileUtils.java index 5d99475..77e49e8 100644 --- a/core/src/main/java/de/neitzel/core/io/FileUtils.java +++ b/core/src/main/java/de/neitzel/core/io/FileUtils.java @@ -3,7 +3,15 @@ package de.neitzel.core.io; import de.neitzel.core.util.ArrayUtils; import lombok.extern.slf4j.Slf4j; -import java.io.*; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; diff --git a/core/src/main/java/de/neitzel/core/io/StringEncoder.java b/core/src/main/java/de/neitzel/core/io/StringEncoder.java index 723d27f..e71c32f 100644 --- a/core/src/main/java/de/neitzel/core/io/StringEncoder.java +++ b/core/src/main/java/de/neitzel/core/io/StringEncoder.java @@ -13,7 +13,7 @@ public class StringEncoder { * static utility methods for array-related operations. * * @throws UnsupportedOperationException always, to indicate that this class - * should not be instantiated. + * should not be instantiated. */ private StringEncoder() { throw new UnsupportedOperationException("Utility class"); @@ -27,7 +27,7 @@ public class StringEncoder { * @param data the string to decode; may contain encoded characters or regular text. If null, an empty string is returned. * @return the decoded string with all encoded characters replaced by their original representations. * @throws IllegalArgumentException if the input string has encoding markup - * that is improperly formatted or incomplete. + * that is improperly formatted or incomplete. */ public static String decodeData(final String data) { if (data == null) return ""; @@ -38,17 +38,17 @@ public class StringEncoder { int indexAmp = remaining.indexOf("&"); if (indexAmp == -1) { result.append(remaining); - remaining=""; + remaining = ""; } else { // First get the elements till the & if (indexAmp > 0) { result.append(remaining.substring(0, indexAmp)); remaining = remaining.substring(indexAmp); } - int endSpecial=remaining.indexOf(";"); + int endSpecial = remaining.indexOf(";"); if (endSpecial == -1) throw new IllegalArgumentException("String couldn't be decoded! (" + data + ")"); - String special = remaining.substring(0, endSpecial+1); - remaining = remaining.substring(endSpecial+1); + String special = remaining.substring(0, endSpecial + 1); + remaining = remaining.substring(endSpecial + 1); result.append(decodeCharacter(special)); } } @@ -67,7 +67,7 @@ public class StringEncoder { public static char decodeCharacter(final String data) { if (!data.startsWith("&#")) throw new IllegalArgumentException("Data does not start with &# (" + data + ")"); if (!data.endsWith(";")) throw new IllegalArgumentException("Data does not end with ; (" + data + ")"); - return (char)Integer.parseInt(data.substring(2, data.length()-1)); + return (char) Integer.parseInt(data.substring(2, data.length() - 1)); } /** @@ -77,16 +77,16 @@ public class StringEncoder { * * @param data the input string to encode; if null, an empty string is returned * @return an encoded string where non-ASCII and ampersand characters - * are replaced with numeric character references + * are replaced with numeric character references */ public static String encodeData(final String data) { if (data == null) return ""; StringBuilder result = new StringBuilder(); - for (int index=0; index < data.length(); index++) { + for (int index = 0; index < data.length(); index++) { char character = data.charAt(index); if (character < 32 || character > 127 || character == 38) { - result.append("&#" + (int)character + ";"); + result.append("&#" + (int) character + ";"); } else { result.append(character); } diff --git a/core/src/main/java/de/neitzel/core/sound/ToneGenerator.java b/core/src/main/java/de/neitzel/core/sound/ToneGenerator.java index 9e92c17..0093f8b 100644 --- a/core/src/main/java/de/neitzel/core/sound/ToneGenerator.java +++ b/core/src/main/java/de/neitzel/core/sound/ToneGenerator.java @@ -16,16 +16,30 @@ public class ToneGenerator { * static utility methods for array-related operations. * * @throws UnsupportedOperationException always, to indicate that this class - * should not be instantiated. + * should not be instantiated. */ private ToneGenerator() { throw new UnsupportedOperationException("Utility class"); } + /** + * Plays one or more specified tones for a given duration. + * Each tone is played sequentially in the order they are provided. + * + * @param duration the duration of each tone in milliseconds + * @param tones the names of the tones to play, specified as a variable-length argument + * @throws LineUnavailableException if the audio line cannot be opened or accessed + */ + public static void playTone(int duration, String... tones) throws LineUnavailableException { + for (String tone : tones) { + playTone(tone, duration); + } + } + /** * Plays a tone based on a predefined tone name for a specified duration. * - * @param tone The name of the tone to play. Must correspond to a predefined tone in the tone table. + * @param tone The name of the tone to play. Must correspond to a predefined tone in the tone table. * @param duration The duration of the tone in milliseconds. * @throws LineUnavailableException If a line for audio playback cannot be opened. */ @@ -64,18 +78,4 @@ public class ToneGenerator { line.drain(); } } - - /** - * Plays one or more specified tones for a given duration. - * Each tone is played sequentially in the order they are provided. - * - * @param duration the duration of each tone in milliseconds - * @param tones the names of the tones to play, specified as a variable-length argument - * @throws LineUnavailableException if the audio line cannot be opened or accessed - */ - public static void playTone(int duration, String... tones) throws LineUnavailableException { - for (String tone : tones) { - playTone(tone, duration); - } - } } diff --git a/core/src/main/java/de/neitzel/core/sound/ToneTable.java b/core/src/main/java/de/neitzel/core/sound/ToneTable.java index e592ae0..9990190 100644 --- a/core/src/main/java/de/neitzel/core/sound/ToneTable.java +++ b/core/src/main/java/de/neitzel/core/sound/ToneTable.java @@ -7,34 +7,23 @@ import java.util.HashMap; * with their corresponding frequencies in hertz (Hz). It allows users to * retrieve the frequency of a tone based on its standard notation name, * such as "C3", "A4", or "G#5". - * + *

* This class can be particularly useful in applications related to sound synthesis, * music theory, signal processing, and other audio-related domains that require precise * frequency information for specific tones. */ public class ToneTable { - /** - * Private constructor to prevent instantiation of the utility class. - * This utility class is not meant to be instantiated, as it only provides - * static utility methods for array-related operations. - * - * @throws UnsupportedOperationException always, to indicate that this class - * should not be instantiated. - */ - private ToneTable() { - throw new UnsupportedOperationException("Utility class"); - } - /** * A static map that associates written tone names with their corresponding frequencies in hertz (Hz). * The keys represent tone names (e.g., "C4", "D#5"), and the values are their respective frequencies. * This map serves as a reference for converting tone names into their precise frequency values, * which are used in applications such as tone generation or audio playback. - * + *

* The map is a crucial component of the ToneTable class, providing quick lookup of frequencies * for predefined tone names. */ private static final HashMap toneMap = new HashMap<>(); + static { toneMap.put("C0", 16.35); toneMap.put("C#0", 17.32); @@ -191,6 +180,18 @@ public class ToneTable { toneMap.put("B8", 7902.13); } + /** + * Private constructor to prevent instantiation of the utility class. + * This utility class is not meant to be instantiated, as it only provides + * static utility methods for array-related operations. + * + * @throws UnsupportedOperationException always, to indicate that this class + * should not be instantiated. + */ + private ToneTable() { + throw new UnsupportedOperationException("Utility class"); + } + /** * Retrieves the frequency of the tone based on the given tone name. * If the tone name exists in the tone map, its corresponding frequency is returned. diff --git a/core/src/main/java/de/neitzel/core/sql/Query.java b/core/src/main/java/de/neitzel/core/sql/Query.java index d139534..e588f11 100644 --- a/core/src/main/java/de/neitzel/core/sql/Query.java +++ b/core/src/main/java/de/neitzel/core/sql/Query.java @@ -8,7 +8,14 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Scanner; +import java.util.Spliterator; +import java.util.Spliterators; import java.util.function.Function; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -23,311 +30,312 @@ import java.util.stream.StreamSupport; @Slf4j public class Query { - /** - * A factory function that extracts an Integer from the first column of a given ResultSet. - *

- * This function is designed to facilitate the conversion of a ResultSet row into an Integer - * by accessing the value in the first column of the result set. If an SQL exception is encountered - * during the retrieval of the integer value, it is wrapped and re-thrown as a runtime exception. - */ - public static final Function INTEGER_FACTORY = rs -> { - try { - return rs.getInt(1); - } catch (SQLException e) { - throw new RuntimeException(e); - } - }; - - /** - * Represents a database connection instance. - * This connection is used to interact with a database - * through executing queries and retrieving results. - * It is immutable and initialized once. - */ - private final Connection connection; - - /** - * A list of ParameterSetter objects used to configure parameters. - * This collection serves as a storage for managing parameter-setting logic dynamically. - * It is initialized as an empty ArrayList and is immutable since it is declared as final. - */ - private final List parameterSetters = new ArrayList<>(); - - /** - * A functional interface representing a factory method used to produce instances of type T. - * This factory is typically implemented to map rows from a {@link ResultSet} to objects of type T. - * The input parameter is a {@link ResultSet}, which provides access to database query results. - * The resulting output is an instance of type T created based on the data in the provided ResultSet. - */ - private Function factory; - - /** - * Represents the text of a query. - * This variable stores the query string used for processing or execution purposes within the application. - */ - private String queryText; - - /** - * Constructs a new Query object with the given database connection. - * - * @param connection The Connection object used to interact with the database. - */ - public Query(Connection connection) { - this.connection = connection; - } - - /** - * Executes the given SQL query using the provided database connection. - * - * @param connection the database connection to be used for executing the query - * @param query the SQL query to be executed - * @throws SQLException if a database access error occurs or the query execution fails - */ - public static void execute(final Connection connection, final String query) throws SQLException { - new Query(connection) - .setQueryText(query) - .execute(); - } - - /** - * Sets the query text for the current query instance. - * - * @param queryText the text of the query to be set - * @return the current instance of the query - */ - public Query setQueryText(final String queryText) { - this.queryText = queryText; - return this; - } - - /** - * Sets the query resource by loading its content from the given resource path. - * The resource content is read and stored as the query text for the query object. - * - * @param resourcePath the path to the resource file containing the query text - * @return the current Query object with the loaded query text - */ - public Query setQueryResource(final String resourcePath) { - log.info("loading resource: {}", resourcePath); - try (Scanner scanner = new Scanner(Objects.requireNonNull(getClass().getResourceAsStream(resourcePath)), - StandardCharsets.UTF_8)) { - this.queryText = scanner.useDelimiter("\\A").next(); - } - log.info("query text: {}", this.queryText); - return this; - } - - /** - * Replaces all occurrences of the specified placeholder in the query text with the provided value. - * - * @param placeholder the placeholder string to be replaced in the query text - * @param value the value to replace the placeholder with - * @return the updated Query instance with the modified query text - */ - public Query replace(final String placeholder, final String value) { - this.queryText = this.queryText.replace(placeholder, value); - log.info("query text: {}", this.queryText); - return this; - } - - /** - * Adds a parameter to the query at the specified index with a custom setter function. - * - * @param index The position of the parameter in the query starting from 1. - * @param value The value of the parameter to be set. - * @param setter A TriSqlFunction that defines how to set the parameter in the PreparedStatement. - * @param The type of the parameter value. - * @return The current query instance for method chaining. - */ - public Query addParameter(final int index, final X value, final TriSqlFunction setter) { - parameterSetters.add(ps -> setter.apply(ps, index, value)); - return this; - } - - /** - * Adds a parameter to the query using the specified ParameterSetter. - * - * @param setter the ParameterSetter used to configure the parameter - * @return the current Query instance for method chaining - */ - public Query addParameter(ParameterSetter setter) { - parameterSetters.add(setter); - return this; - } - - /** - * Sets the factory function used to convert a {@link ResultSet} into an instance of type {@code T}. - * - * @param factory the function responsible for mapping a {@code ResultSet} to an object of type {@code T} - * @return the current {@code Query} instance with the specified factory function set - */ - public Query factory(final Function factory) { - this.factory = factory; - return this; - } - - /** - * Creates a {@link Stream} from the result set obtained by executing a prepared statement. - * The result set is wrapped in a {@link TrimmingResultSet} to handle data trimming. - * - * @return a {@link Stream} of type T populated with the query results processed using the specified factory - * @throws SQLException if an SQL error occurs while executing the prepared statement or creating the stream - */ - private Stream stream() throws SQLException { - ResultSet rs = createPreparedStatement().executeQuery(); - TrimmingResultSet trimmingResultSet = new TrimmingResultSet(rs); - return streamFromResultSet(trimmingResultSet, factory); - } - - /** - * Creates and returns a PreparedStatement object configured with the query text - * and parameters defined for the current instance. - * - * @return a PreparedStatement object initialized with the query and parameter values - * @throws SQLException if a database access error occurs or the PreparedStatement cannot be created - */ - private PreparedStatement createPreparedStatement() throws SQLException { - PreparedStatement ps = connection.prepareStatement(queryText); - for (ParameterSetter setter : parameterSetters) { - setter.apply(ps); - } - return ps; - } - - /** - * Executes the SQL statement represented by the PreparedStatement created in - * the method {@code createPreparedStatement()}. This method is used to perform - * database operations such as updates or other actions that do not produce a - * result set. - * - * @throws SQLException if a database access error occurs or the SQL statement is invalid. - */ - public void execute() throws SQLException { - try (PreparedStatement ps = createPreparedStatement()) { - ps.execute(); - } - } - - /** - * Converts a {@link ResultSet} into a {@link Stream} of objects created using the provided {@link Function} - * factory. The stream ensures resources such as the {@code ResultSet} and its associated statement are - * closed when the stream is closed. - * - * @param rs the {@link ResultSet} to be transformed into a stream - * @param factory a {@link Function} that maps rows of the {@link ResultSet} to objects of type T - * @return a {@link Stream} of objects of type T created from the {@code ResultSet} rows - */ - private Stream streamFromResultSet(final ResultSet rs, final Function factory) { - Iterator iterator = new Iterator<>() { - private boolean hasNextChecked = false; - private boolean hasNext; - - /** - * Checks if the iteration has more elements. This method verifies if the - * underlying {@link ResultSet} contains another row that has not yet been processed. - * - * @return {@code true} if there are more elements in the {@link ResultSet}, - * otherwise {@code false}. - */ - @Override - @SneakyThrows - public boolean hasNext() { - if (!hasNextChecked) { - hasNext = rs.next(); - hasNextChecked = true; + /** + * A factory function that extracts an Integer from the first column of a given ResultSet. + *

+ * This function is designed to facilitate the conversion of a ResultSet row into an Integer + * by accessing the value in the first column of the result set. If an SQL exception is encountered + * during the retrieval of the integer value, it is wrapped and re-thrown as a runtime exception. + */ + public static final Function INTEGER_FACTORY = rs -> { + try { + return rs.getInt(1); + } catch (SQLException e) { + throw new RuntimeException(e); } - return hasNext; - } - - /** - * Returns the next element in the iteration. This method applies the provided - * factory function to the current row of the {@link ResultSet} to create an object of type T. - * It throws {@link NoSuchElementException} if there are no more elements to iterate. - * - * @return the next element of type T as created by the factory function from the current row of the {@link ResultSet} - * @throws NoSuchElementException if the iteration has no more elements - */ - @Override - public T next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - hasNextChecked = false; - return factory.apply(rs); - } }; - Spliterator spliterator = Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED); - return StreamSupport.stream(spliterator, false) - .onClose(() -> { - try { - rs.getStatement().close(); - } catch (SQLException ignored) { - // Exception is ignored. - } - try { - rs.close(); - } catch (SQLException ignored) { - // Exception is ignored. - } - }); - } - /** - * Provides a managed stream to the given handler and ensures proper resource closing after use. - * A {@code Stream} is opened and passed to the specified handler as an argument. - * The stream will be automatically closed when the handler finishes execution or throws an exception. - * - * @param handler a function which receives a {@code Stream} and processes it, returning a result of type {@code R}. - * @param the type of the result produced by the handler. - * @return the result returned by the handler after processing the stream. - * @throws SQLException if an SQL error occurs during the creation or handling of the stream. - */ - public R withStream(Function, R> handler) throws SQLException { - try (Stream stream = stream()) { - return handler.apply(stream); + /** + * Represents a database connection instance. + * This connection is used to interact with a database + * through executing queries and retrieving results. + * It is immutable and initialized once. + */ + private final Connection connection; + + /** + * A list of ParameterSetter objects used to configure parameters. + * This collection serves as a storage for managing parameter-setting logic dynamically. + * It is initialized as an empty ArrayList and is immutable since it is declared as final. + */ + private final List parameterSetters = new ArrayList<>(); + + /** + * A functional interface representing a factory method used to produce instances of type T. + * This factory is typically implemented to map rows from a {@link ResultSet} to objects of type T. + * The input parameter is a {@link ResultSet}, which provides access to database query results. + * The resulting output is an instance of type T created based on the data in the provided ResultSet. + */ + private Function factory; + + /** + * Represents the text of a query. + * This variable stores the query string used for processing or execution purposes within the application. + */ + private String queryText; + + /** + * Constructs a new Query object with the given database connection. + * + * @param connection The Connection object used to interact with the database. + */ + public Query(Connection connection) { + this.connection = connection; } - } - - /** - * Represents a functional interface that accepts three input arguments and allows for operations - * that can throw an {@link SQLException}. This can be useful in scenarios where SQL-related - * logic requires processing with three parameters. - * - * @param the type of the first input to the operation - * @param the type of the second input to the operation - * @param the type of the third input to the operation - */ - @FunctionalInterface - public interface TriSqlFunction { /** - * Executes an operation on three input arguments and allows for the operation to throw - * an {@link SQLException}. This method is intended to facilitate SQL-related processes - * where three parameters are involved. + * Executes the given SQL query using the provided database connection. * - * @param t the first input argument - * @param u the second input argument - * @param v the third input argument - * @throws SQLException if an SQL error occurs during execution + * @param connection the database connection to be used for executing the query + * @param query the SQL query to be executed + * @throws SQLException if a database access error occurs or the query execution fails */ - void apply(T t, U u, V v) throws SQLException; - } - - /** - * Functional interface designed to handle operations on a PreparedStatement. - * Represents a single abstract method that performs specific work on the - * provided PreparedStatement instance. - */ - @FunctionalInterface - public interface ParameterSetter { + public static void execute(final Connection connection, final String query) throws SQLException { + new Query(connection) + .setQueryText(query) + .execute(); + } /** - * Applies an operation to the given PreparedStatement object. - * This method is intended to set parameters or perform other modifications on a PreparedStatement. + * Executes the SQL statement represented by the PreparedStatement created in + * the method {@code createPreparedStatement()}. This method is used to perform + * database operations such as updates or other actions that do not produce a + * result set. * - * @param ps the PreparedStatement instance to be modified or configured - * @throws SQLException if a database access error occurs while applying the operation + * @throws SQLException if a database access error occurs or the SQL statement is invalid. */ - void apply(PreparedStatement ps) throws SQLException; - } + public void execute() throws SQLException { + try (PreparedStatement ps = createPreparedStatement()) { + ps.execute(); + } + } + + /** + * Sets the query text for the current query instance. + * + * @param queryText the text of the query to be set + * @return the current instance of the query + */ + public Query setQueryText(final String queryText) { + this.queryText = queryText; + return this; + } + + /** + * Creates and returns a PreparedStatement object configured with the query text + * and parameters defined for the current instance. + * + * @return a PreparedStatement object initialized with the query and parameter values + * @throws SQLException if a database access error occurs or the PreparedStatement cannot be created + */ + private PreparedStatement createPreparedStatement() throws SQLException { + PreparedStatement ps = connection.prepareStatement(queryText); + for (ParameterSetter setter : parameterSetters) { + setter.apply(ps); + } + return ps; + } + + /** + * Sets the query resource by loading its content from the given resource path. + * The resource content is read and stored as the query text for the query object. + * + * @param resourcePath the path to the resource file containing the query text + * @return the current Query object with the loaded query text + */ + public Query setQueryResource(final String resourcePath) { + log.info("loading resource: {}", resourcePath); + try (Scanner scanner = new Scanner(Objects.requireNonNull(getClass().getResourceAsStream(resourcePath)), + StandardCharsets.UTF_8)) { + this.queryText = scanner.useDelimiter("\\A").next(); + } + log.info("query text: {}", this.queryText); + return this; + } + + /** + * Replaces all occurrences of the specified placeholder in the query text with the provided value. + * + * @param placeholder the placeholder string to be replaced in the query text + * @param value the value to replace the placeholder with + * @return the updated Query instance with the modified query text + */ + public Query replace(final String placeholder, final String value) { + this.queryText = this.queryText.replace(placeholder, value); + log.info("query text: {}", this.queryText); + return this; + } + + /** + * Adds a parameter to the query at the specified index with a custom setter function. + * + * @param index The position of the parameter in the query starting from 1. + * @param value The value of the parameter to be set. + * @param setter A TriSqlFunction that defines how to set the parameter in the PreparedStatement. + * @param The type of the parameter value. + * @return The current query instance for method chaining. + */ + public Query addParameter(final int index, final X value, final TriSqlFunction setter) { + parameterSetters.add(ps -> setter.apply(ps, index, value)); + return this; + } + + /** + * Adds a parameter to the query using the specified ParameterSetter. + * + * @param setter the ParameterSetter used to configure the parameter + * @return the current Query instance for method chaining + */ + public Query addParameter(ParameterSetter setter) { + parameterSetters.add(setter); + return this; + } + + /** + * Sets the factory function used to convert a {@link ResultSet} into an instance of type {@code T}. + * + * @param factory the function responsible for mapping a {@code ResultSet} to an object of type {@code T} + * @return the current {@code Query} instance with the specified factory function set + */ + public Query factory(final Function factory) { + this.factory = factory; + return this; + } + + /** + * Provides a managed stream to the given handler and ensures proper resource closing after use. + * A {@code Stream} is opened and passed to the specified handler as an argument. + * The stream will be automatically closed when the handler finishes execution or throws an exception. + * + * @param handler a function which receives a {@code Stream} and processes it, returning a result of type {@code R}. + * @param the type of the result produced by the handler. + * @return the result returned by the handler after processing the stream. + * @throws SQLException if an SQL error occurs during the creation or handling of the stream. + */ + public R withStream(Function, R> handler) throws SQLException { + try (Stream stream = stream()) { + return handler.apply(stream); + } + } + + /** + * Creates a {@link Stream} from the result set obtained by executing a prepared statement. + * The result set is wrapped in a {@link TrimmingResultSet} to handle data trimming. + * + * @return a {@link Stream} of type T populated with the query results processed using the specified factory + * @throws SQLException if an SQL error occurs while executing the prepared statement or creating the stream + */ + private Stream stream() throws SQLException { + ResultSet rs = createPreparedStatement().executeQuery(); + TrimmingResultSet trimmingResultSet = new TrimmingResultSet(rs); + return streamFromResultSet(trimmingResultSet, factory); + } + + /** + * Converts a {@link ResultSet} into a {@link Stream} of objects created using the provided {@link Function} + * factory. The stream ensures resources such as the {@code ResultSet} and its associated statement are + * closed when the stream is closed. + * + * @param rs the {@link ResultSet} to be transformed into a stream + * @param factory a {@link Function} that maps rows of the {@link ResultSet} to objects of type T + * @return a {@link Stream} of objects of type T created from the {@code ResultSet} rows + */ + private Stream streamFromResultSet(final ResultSet rs, final Function factory) { + Iterator iterator = new Iterator<>() { + private boolean hasNextChecked = false; + + private boolean hasNext; + + /** + * Checks if the iteration has more elements. This method verifies if the + * underlying {@link ResultSet} contains another row that has not yet been processed. + * + * @return {@code true} if there are more elements in the {@link ResultSet}, + * otherwise {@code false}. + */ + @Override + @SneakyThrows + public boolean hasNext() { + if (!hasNextChecked) { + hasNext = rs.next(); + hasNextChecked = true; + } + return hasNext; + } + + /** + * Returns the next element in the iteration. This method applies the provided + * factory function to the current row of the {@link ResultSet} to create an object of type T. + * It throws {@link NoSuchElementException} if there are no more elements to iterate. + * + * @return the next element of type T as created by the factory function from the current row of the {@link ResultSet} + * @throws NoSuchElementException if the iteration has no more elements + */ + @Override + public T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + hasNextChecked = false; + return factory.apply(rs); + } + }; + Spliterator spliterator = Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED); + return StreamSupport.stream(spliterator, false) + .onClose(() -> { + try { + rs.getStatement().close(); + } catch (SQLException ignored) { + // Exception is ignored. + } + try { + rs.close(); + } catch (SQLException ignored) { + // Exception is ignored. + } + }); + } + + /** + * Represents a functional interface that accepts three input arguments and allows for operations + * that can throw an {@link SQLException}. This can be useful in scenarios where SQL-related + * logic requires processing with three parameters. + * + * @param the type of the first input to the operation + * @param the type of the second input to the operation + * @param the type of the third input to the operation + */ + @FunctionalInterface + public interface TriSqlFunction { + + /** + * Executes an operation on three input arguments and allows for the operation to throw + * an {@link SQLException}. This method is intended to facilitate SQL-related processes + * where three parameters are involved. + * + * @param t the first input argument + * @param u the second input argument + * @param v the third input argument + * @throws SQLException if an SQL error occurs during execution + */ + void apply(T t, U u, V v) throws SQLException; + } + + /** + * Functional interface designed to handle operations on a PreparedStatement. + * Represents a single abstract method that performs specific work on the + * provided PreparedStatement instance. + */ + @FunctionalInterface + public interface ParameterSetter { + + /** + * Applies an operation to the given PreparedStatement object. + * This method is intended to set parameters or perform other modifications on a PreparedStatement. + * + * @param ps the PreparedStatement instance to be modified or configured + * @throws SQLException if a database access error occurs while applying the operation + */ + void apply(PreparedStatement ps) throws SQLException; + } } diff --git a/core/src/main/java/de/neitzel/core/sql/TrimmingResultSet.java b/core/src/main/java/de/neitzel/core/sql/TrimmingResultSet.java index 19ae0c0..eddefb8 100644 --- a/core/src/main/java/de/neitzel/core/sql/TrimmingResultSet.java +++ b/core/src/main/java/de/neitzel/core/sql/TrimmingResultSet.java @@ -4,7 +4,22 @@ import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.net.URL; -import java.sql.*; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.NClob; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLType; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; import java.util.Calendar; import java.util.Map; @@ -18,2647 +33,2653 @@ import java.util.Map; */ public class TrimmingResultSet implements ResultSet { - /** - * Represents the result set obtained from executing a database query. - * This object provides functionality to traverse and access the data - * in a tabular format returned by the query execution. - * - * This ResultSet instance is immutable and cannot be modified after initialization. - * It is typically used for reading query results and is tied to a specific - * SQL query execution lifecycle. - */ - private final ResultSet resultSet; - - /** - * Initializes a new instance of the TrimmingResultSet class, wrapping the provided ResultSet. - * - * @param resultSet the ResultSet to be wrapped and processed by this TrimmingResultSet instance - */ - public TrimmingResultSet(ResultSet resultSet) { - this.resultSet = resultSet; - } - - /** - * Retrieves the string value from the specified column index of the current row in the ResultSet. - * The value is trimmed to remove leading and trailing whitespace. If the value is null, it returns null. - * - * @param columnIndex the column index, starting from 1, from which the string is to be retrieved - * @return the trimmed string value from the specified column, or null if the column value is SQL NULL - * @throws SQLException if a database access error occurs or the columnIndex is not valid - */ - @Override - public String getString(final int columnIndex) throws SQLException { - String value = resultSet.getString(columnIndex); - return value != null ? value.trim() : null; - } - - /** - * Retrieves the value of the specified column as a trimmed string. - * - * @param columnLabel the label of the column from which to retrieve the value - * @return the trimmed string value of the specified column, or null if the column value is SQL NULL - * @throws SQLException if a database access error occurs or the columnLabel is invalid - */ - @Override - public String getString(final String columnLabel) throws SQLException { - String value = resultSet.getString(columnLabel); - return value != null ? value.trim() : null; - } - - /** - * Moves the cursor forward one row from its current position in the ResultSet. - * - * @return true if the new current row is valid, false if there are no more rows - * @throws SQLException if a database access error occurs or this method is called on a closed ResultSet - */ - @Override - public boolean next() throws SQLException { - return resultSet.next(); - } - - /** - * Closes the current resource associated with this instance. - * This method ensures that the ResultSet object is properly closed to - * release database and JDBC resources. - * - * @throws SQLException if a database access error occurs while closing the ResultSet. - */ - @Override - public void close() throws SQLException { - resultSet.close(); - } - - /** - * Checks if the last column read had a value of SQL NULL. - * This method should be called only after calling a getter method - * on the ResultSet to retrieve a column value. - * - * @return true if the last column read was SQL NULL; false otherwise - * @throws SQLException if a database access error occurs - */ - @Override - public boolean wasNull() throws SQLException { - return resultSet.wasNull(); - } - - /** - * Retrieves the value of the designated column in the current row of the result set - * as a boolean. - * - * @param columnIndex the index of the column, starting from 1 - * @return the column value as a boolean - * @throws SQLException if a database access error occurs or the columnIndex is out of bounds - */ - @Override - public boolean getBoolean(final int columnIndex) throws SQLException { - return resultSet.getBoolean(columnIndex); - } - - /** - * Retrieves the value of the designated column as a boolean. - * - * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, - * then the label is the name of the column. - * @return the column value as a boolean. Returns false if the value in the designated column is SQL NULL. - * @throws SQLException if a database access error occurs or the column label is not valid. - */ - @Override - public boolean getBoolean(final String columnLabel) throws SQLException { - return resultSet.getBoolean(columnLabel); - } - - /** - * Retrieves the value of the designated column in the current row - * of this ResultSet object as a byte. - * - * @param columnIndex the first column is 1, the second is 2, and so on; - * must be a valid column index - * @return the column value as a byte - * @throws SQLException if the column index is invalid or if a database access error occurs - */ - @Override - public byte getByte(final int columnIndex) throws SQLException { - return resultSet.getByte(columnIndex); - } - - /** - * Retrieves the value of the designated column in the current row of this ResultSet - * object as a byte. - * - * @param columnLabel the label for the column specified with the SQL AS clause. - * If the SQL AS clause was not specified, then the label is - * the name of the column. - * @return the column value as a byte. If the value is SQL NULL, the result is 0. - * @throws SQLException if the columnLabel is not valid or a database access error occurs. - */ - @Override - public byte getByte(final String columnLabel) throws SQLException { - return resultSet.getByte(columnLabel); - } - - /** - * Retrieves the value of the designated column in the current row of this ResultSet object - * as a short. - * - * @param columnIndex the column index, starting from 1, which indicates the column to retrieve - * the short value from - * @return the column value as a short - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public short getShort(final int columnIndex) throws SQLException { - return resultSet.getShort(columnIndex); - } - - /** - * Retrieves the value of the specified column as a short. - * - * @param columnLabel the label for the column specified with the SQL query - * @return the column value as a short - * @throws SQLException if a database access error occurs or the columnLabel is not valid - */ - @Override - public short getShort(final String columnLabel) throws SQLException { - return resultSet.getShort(columnLabel); - } - - /** - * Retrieves the value of the column specified by the given index as an int. - * - * @param columnIndex the index of the column in the current row, starting from 1 - * @return the column value as an int - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public int getInt(final int columnIndex) throws SQLException { - return resultSet.getInt(columnIndex); - } - - /** - * Retrieves the value of the column designated by the given label as an int. - * - * @param columnLabel the label for the column specified with the SQL AS clause, or the original column name - * @return the column value as an int - * @throws SQLException if a database access error occurs or the column label is not valid - */ - @Override - public int getInt(final String columnLabel) throws SQLException { - return resultSet.getInt(columnLabel); - } - - /** - * Retrieves the value of the designated column in the current row of the ResultSet - * as a long value. - * - * @param columnIndex the index of the column from which to retrieve the value, starting from 1 - * @return the long value of the designated column - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public long getLong(final int columnIndex) throws SQLException { - return resultSet.getLong(columnIndex); - } - - /** - * Retrieves the value of the specified column as a long. - * - * @param columnLabel the name of the column from which to retrieve the value - * @return the long value of the specified column - * @throws SQLException if a database access error occurs or the column label is not valid - */ - @Override - public long getLong(final String columnLabel) throws SQLException { - return resultSet.getLong(columnLabel); - } - - /** - * Retrieves the value of the designated column in the current row of this - * ResultSet as a float. - * - * @param columnIndex the index of the column, starting from 1, from which - * the float value is to be retrieved - * @return the column value as a float - * @throws SQLException if a database access error occurs or the column - * index is invalid - */ - @Override - public float getFloat(final int columnIndex) throws SQLException { - return resultSet.getFloat(columnIndex); - } - - /** - * Retrieves the value of the specified column as a float from the result set. - * - * @param columnLabel the label for the column specified in the SQL query - * @return the column value as a float - * @throws SQLException if a database access error occurs or the columnLabel is not valid - */ - @Override - public float getFloat(final String columnLabel) throws SQLException { - return resultSet.getFloat(columnLabel); - } - - /** - * Retrieves the value of the designated column in the current row of this - * ResultSet object as a double. - * - * @param columnIndex the index of the column, starting from 1, from which - * the double value is to be retrieved - * @return the column value as a double - * @throws SQLException if a database access error occurs or the column - * index is invalid - */ - @Override - public double getDouble(final int columnIndex) throws SQLException { - return resultSet.getDouble(columnIndex); - } - - /** - * Retrieves the value of the designated column as a double. - * - * @param columnLabel the label for the column specified in the SQL query - * @return the column value as a double - * @throws SQLException if a database access error occurs or the columnLabel is not valid - */ - @Override - public double getDouble(final String columnLabel) throws SQLException { - return resultSet.getDouble(columnLabel); - } - - /** - * Retrieves the value of the specified column as a BigDecimal object with the specified scale. - * - * @param columnIndex the index of the column (1-based) from which to retrieve the BigDecimal value - * @param scale the scale to apply to the retrieved BigDecimal value - * @return the BigDecimal value from the specified column with the given scale - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - @Deprecated - public BigDecimal getBigDecimal(final int columnIndex, int scale) throws SQLException { - return resultSet.getBigDecimal(columnIndex, scale); - } - - /** - * Retrieves the value of the specified column as a {@code BigDecimal} object. - * - * @param columnIndex the column index (starting at 1) from which the BigDecimal value is to be retrieved - * @return the column value as a {@code BigDecimal}, or null if the column value is SQL NULL - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public BigDecimal getBigDecimal(final int columnIndex) throws SQLException { - return resultSet.getBigDecimal(columnIndex); - } - - /** - * Retrieves the value of the designated column as a {@code BigDecimal} with the specified scale. - * - * @param columnLabel the label for the column in the SQL result set - * @param scale the number of digits to the right of the decimal point - * @return the value of the column as a {@code BigDecimal} with the specified scale - * @throws SQLException if a database access error occurs or this method is called on a closed result set - */ - @Override - @Deprecated - public BigDecimal getBigDecimal(final String columnLabel, int scale) throws SQLException { - return resultSet.getBigDecimal(columnLabel, scale); - } - - /** - * Retrieves the value of the specified column as a {@code BigDecimal} object. - * - * @param columnLabel the label of the column from which to retrieve the value - * @return the column value as a {@code BigDecimal} object, or {@code null} if the value is SQL {@code NULL} - * @throws SQLException if an SQL error occurs while retrieving the value - */ - @Override - public BigDecimal getBigDecimal(final String columnLabel) throws SQLException { - return resultSet.getBigDecimal(columnLabel); - } - - /** - * Retrieves the value of the designated column in the current row of this ResultSet - * object as a byte array. - * - * @param columnIndex the first column is 1, the second is 2, and so on; indicates - * which column value to retrieve. - * @return the column value as a byte array. Returns null if the SQL value is - * SQL NULL. - * @throws SQLException if the columnIndex is invalid or a database access error occurs. - */ - @Override - public byte[] getBytes(final int columnIndex) throws SQLException { - return resultSet.getBytes(columnIndex); - } - - /** - * Retrieves the value of the specified column in the current row of this ResultSet - * as a byte array. The column is specified using the column label. - * - * @param columnLabel the label for the column from which to retrieve the value - * @return a byte array containing the column value; null if the value is SQL NULL - * @throws SQLException if a database access error occurs or the column label is invalid - */ - @Override - public byte[] getBytes(final String columnLabel) throws SQLException { - return resultSet.getBytes(columnLabel); - } - - /** - * Retrieves the value of the designated column in the current row of this result set - * as a {@code Date} object. - * - * @param columnIndex the first column is 1, the second column is 2, and so on - * @return the {@code Date} value of the specified column in the current row - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public Date getDate(final int columnIndex) throws SQLException { - return resultSet.getDate(columnIndex); - } - - /** - * Retrieves the date value of the specified column. - * - * @param columnLabel the label of the column from which the date value is to be retrieved - * @return the date value of the specified column, or null if the value is SQL NULL - * @throws SQLException if a database access error occurs or the column label is invalid - */ - @Override - public Date getDate(final String columnLabel) throws SQLException { - return resultSet.getDate(columnLabel); - } - - /** - * Retrieves the value of the designated column as a Date object - * using the given Calendar object for interpreting the timezone. - * - * @param columnIndex the index of the column, starting from 1 - * @param cal the Calendar object to use for interpreting dates, or null - * @return the value of the column as a Date object; - * if the value is SQL NULL, the result is null - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public Date getDate(final int columnIndex, final Calendar cal) throws SQLException { - return resultSet.getDate(columnIndex, cal); - } - - /** - * Retrieves the value of the specified column as a Date object using the given Calendar instance to construct the date. - * - * @param columnLabel the label for the column from which to retrieve the value - * @param cal the Calendar instance to use for determining the date - * @return the column value as a Date object; if the value is SQL NULL, the result is null - * @throws SQLException if a database access error occurs or the column label is invalid - */ - @Override - public Date getDate(final String columnLabel, final Calendar cal) throws SQLException { - return resultSet.getDate(columnLabel, cal); - } - - /** - * Retrieves the value of the designated column as a {@code Time} object. - * - * @param columnIndex the index of the column, starting from 1 - * @return the {@code Time} value of the specified column in the current row - * @throws SQLException if the column index is invalid or a database access error occurs - */ - @Override - public Time getTime(final int columnIndex) throws SQLException { - return resultSet.getTime(columnIndex); - } - - /** - * Retrieves the value of the specified column as a {@code Time} object. - * - * @param columnLabel the label of the column from which to retrieve the value - * @return a {@code Time} object representing the value of the specified column - * @throws SQLException if a database access error occurs or the columnLabel is not valid - */ - @Override - public Time getTime(final String columnLabel) throws SQLException { - return resultSet.getTime(columnLabel); - } - - /** - * Retrieves the value of the designated column as a {@code Time} object. - * - * @param columnIndex an integer indicating the column index, starting at 1 - * @param cal the {@code Calendar} object to use for constructing the {@code Time} object - * @return the column value as a {@code Time} object or null if the column value is SQL {@code NULL} - * @throws SQLException if a database access error occurs, the column index is invalid, - * or the {@code Calendar} object is null - */ - @Override - public Time getTime(final int columnIndex, final Calendar cal) throws SQLException { - return resultSet.getTime(columnIndex, cal); - } - - /** - * Retrieves the value of the specified column as a {@link Time} object using the given calendar for timezone adjustments. - * - * @param columnLabel the label for the column specified with the SQL query - * @param cal the {@link Calendar} object to use in constructing the date - * @return the column value as a {@link Time} object; if the value is SQL {@code NULL}, the result is {@code null} - * @throws SQLException if a database access error occurs or the column label is not valid - */ - @Override - public Time getTime(final String columnLabel, final Calendar cal) throws SQLException { - return resultSet.getTime(columnLabel, cal); - } - - /** - * Retrieves the value of the designated column in the current row of this - * ResultSet object as a Timestamp object. - * - * @param columnIndex the column index, starting at 1, from which the timestamp - * value is to be retrieved - * @return a Timestamp object representing the SQL TIMESTAMP value in the specified - * column of the current row - * @throws SQLException if a database access error occurs, the column index is invalid, - * or the data in the column is not a valid timestamp - */ - @Override - public Timestamp getTimestamp(final int columnIndex) throws SQLException { - return resultSet.getTimestamp(columnIndex); - } - - /** - * Retrieves the timestamp value for the specified column label from the underlying result set. - * - * @param columnLabel the label for the column from which to retrieve the timestamp - * @return the timestamp value of the specified column; may return null if the value is SQL NULL - * @throws SQLException if a database access error occurs or if the column label is invalid - */ - @Override - public Timestamp getTimestamp(final String columnLabel) throws SQLException { - return resultSet.getTimestamp(columnLabel); - } - - /** - * Retrieves the value of the specified column as a {@code Timestamp} object, - * using the provided {@code Calendar} to construct the {@code Timestamp}. - * - * @param columnIndex the index of the column (1-based) whose value is to be retrieved - * @param cal the {@code Calendar} object to use for interpreting the timestamp - * @return the column value as a {@code Timestamp} object; returns {@code null} if the column value is SQL {@code NULL} - * @throws SQLException if the column index is invalid or a database access error occurs - */ - @Override - public Timestamp getTimestamp(final int columnIndex, final Calendar cal) throws SQLException { - return resultSet.getTimestamp(columnIndex, cal); - } - - /** - * Retrieves the value of the designated column as a {@code Timestamp} object in the specified calendar. - * This method uses the provided {@code Calendar} to construct the {@code Timestamp} object. - * - * @param columnLabel the label for the column from which to retrieve the value - * @param cal the {@code Calendar} object to use to construct the timestamp - * @return the column value as a {@code Timestamp}; if the value is SQL {@code NULL}, the value returned is {@code null} - * @throws SQLException if a database access error occurs or the column label is invalid - */ - @Override - public Timestamp getTimestamp(final String columnLabel, final Calendar cal) throws SQLException { - return resultSet.getTimestamp(columnLabel, cal); - } - - /** - * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of ASCII characters. - * - * @param columnIndex the column index, starting from 1, indicating which column's value to retrieve - * @return an InputStream object that contains the ASCII data of the specified column - * @throws SQLException if a database access error occurs or the columnIndex is invalid - */ - @Override - public InputStream getAsciiStream(final int columnIndex) throws SQLException { - return resultSet.getAsciiStream(columnIndex); - } - - /** - * Retrieves the value of the designated column in the current row as a stream of Unicode characters. - * The stream is read in the Java Unicode character format. - * This method is used to access database data as Unicode text. - * - * @param columnIndex the index of the column in the result set, starting from 1 for the first column - * @return an InputStream object that provides a stream of Unicode characters, - * or null if the SQL value is null - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public InputStream getUnicodeStream(final int columnIndex) throws SQLException { - return null; - } - - /** - * Retrieves the value of the specified column as a stream of ASCII characters. - * - * @param columnLabel the label for the column from which the stream will be retrieved - * @return an InputStream object containing the ASCII stream of the designated column value - * @throws SQLException if a database access error occurs or the columnLabel is not valid - */ - @Override - public InputStream getAsciiStream(final String columnLabel) throws SQLException { - return resultSet.getAsciiStream(columnLabel); - } - - /** - * Retrieves the value of the designated column labeled by the given column label - * as a Unicode stream. The data will be returned as a stream of Unicode characters. - * This method is intended for reading long text values or other binary data - * that can be represented as Unicode. - * - * @param columnLabel the label for the column specified in the SQL query - * @return an InputStream containing the Unicode stream of the designated column, - * or null if the value is SQL NULL - * @throws SQLException if a database access error occurs or if the columnLabel - * does not match an existing column - */ - @Override - public InputStream getUnicodeStream(final String columnLabel) throws SQLException { - return null; - } - - /** - * Retrieves the value of the designated*/ - @Override - public InputStream getBinaryStream(final int columnIndex) throws SQLException { - return resultSet.getBinaryStream(columnIndex); - } - - /** - * Retrieves the value of the designated column as a binary input stream. - * - * @param columnLabel the label for the column specified in the SQL query - * @return an InputStream object that contains the binary data of the designated column - * @throws SQLException if the columnLabel is not valid; - * if a database access error occurs; - * or if this method is called on a closed result set - */ - @Override - public InputStream getBinaryStream(final String columnLabel) throws SQLException { - return resultSet.getBinaryStream(columnLabel); - } - - /** - * Retrieves the first warning reported by calls on the underlying object. - * Subsequent warnings on the object are chained to the first SQLWarning object. - * - * @return the first SQLWarning object or null if there are no warnings - * @throws SQLException if a database access error occurs - */ - @Override - public SQLWarning getWarnings() throws SQLException { - return null; - } - - /** - * Retrieves the value of the designated column in the current row of - * this ResultSet object as a java.io.Reader object. - * - * @param columnIndex the column index (1-based) for which the character stream is to be retrieved - * @return a Reader object that contains the data of the specified column; if the value is SQL NULL, this method returns null - * @throws SQLException if a database access error occurs or this method is called on a closed result set - */ - @Override - public Reader getCharacterStream(final int columnIndex) throws SQLException { - return resultSet.getCharacterStream(columnIndex); - } - - /** - * Retrieves the character stream for the value of the specified column label in the current row of this ResultSet. - * This allows reading character data from the column as a Reader. - * - * @param columnLabel the label for the column specified in the ResultSet object, which is typically the SQL AS name if available, or the actual column name. - * @return a Reader object containing the column value as a stream of characters; null if the value is SQL NULL. - * @throws SQLException if a database access error occurs or the columnLabel is not valid. - */ - @Override - public Reader getCharacterStream(final String columnLabel) throws SQLException { - return resultSet.getCharacterStream(columnLabel); - } - - /** - * Retrieves the NString value at the specified column index from the underlying result set. - * If the value is not null, it trims any leading or trailing whitespace characters. - * - * @param columnIndex the index of the column from which to retrieve the NString value, starting from 1 - * @return the trimmed NString value at the specified column index, or null if the value is null - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public String getNString(final int columnIndex) throws SQLException { - String value = resultSet.getNString(columnIndex); - return value != null ? value.trim() : null; - } - - /** - * Retrieves the value of the designated column as a string in the current row of the result set. - * The string is processed to ensure leading and trailing whitespace is removed. - * - * @param columnLabel the label for the column specified in the query - * @return the column value as a trimmed string, or null if the value is SQL NULL - * @throws SQLException if the columnLabel is not valid, if there is a database access error, or other SQL issues occur - */ - @Override - public String getNString(final String columnLabel) throws SQLException { - String value = resultSet.getNString(columnLabel); - return value != null ? value.trim() : null; - } - - /** - * Retrieves the value of the designated column in the current row of - * this ResultSet object as a Reader object. The column value is expected - * to be a national character stream in the Java programming language. - * - * @param columnIndex the column index (1-based) of the desired column in this ResultSet - * @return a Reader object that contains the column value; if the value is SQL NULL, then null is returned - * @throws SQLException if the columnIndex is invalid or a database access error occurs - */ - @Override - public Reader getNCharacterStream(final int columnIndex) throws SQLException { - return resultSet.getNCharacterStream(columnIndex); - } - - /** - * Retrieves the value of the designated column in the current row of this ResultSet - * object as a character stream in the form of a Reader. - * - * @param columnLabel the label for the column specified in the SQL query - * @return a Reader object that contains the column value; if the column value is SQL NULL, the value returned is null - * @throws SQLException if the columnLabel is not valid, the result set is closed, or a database access error occurs - */ - @Override - public Reader getNCharacterStream(final String columnLabel) throws SQLException { - return resultSet.getNCharacterStream(columnLabel); - } - - /** - * Clears all warnings reported on this ResultSet object. - * - * This method delegates the call to the underlying ResultSet's clearWarnings method, - * ensuring that any chain of warnings previously recorded is cleared. - * - * @throws SQLException if a database access error occurs or this method - * is called on a closed ResultSet. - */ - @Override - public void clearWarnings() throws SQLException { - resultSet.clearWarnings(); - } - - /** - * Retrieves the name of the SQL cursor used by this ResultSet object, if available. - * - * @return the name of the SQL cursor, or null if the cursor does not have a name. - * @throws SQLException if a database access error occurs or this method is called on a closed result set. - */ - @Override - public String getCursorName() throws SQLException { - return resultSet.getCursorName(); - } - - /** - * Retrieves the metadata for the result set. - * - * @return a ResultSetMetaData object that contains information about the columns of the result set. - * @throws SQLException if a database access error occurs. - */ - @Override - public ResultSetMetaData getMetaData() throws SQLException { - return resultSet.getMetaData(); - } - - /** - * Retrieves the value of the designated column in the current row of this ResultSet object - * as an Object. The type of the object returned is determined by the SQL type of the column. - * - * @param columnIndex the index of the column to retrieve, where the first column is 1 - * @return the value of the designated column as an Object; returns null if the value is SQL NULL - * @throws SQLException if a database access error occurs or the column index is out of bounds - */ - @Override - public Object getObject(final int columnIndex) throws SQLException { - return resultSet.getObject(columnIndex); - } - - /** - * Retrieves the value of the designated column in the current row of this ResultSet object - * as an Object. - * - * @param columnLabel the label for the column specified with the SQL AS clause. - * If the SQL AS clause was not specified, the label is the name of the column. - * @return the value of the specified column as an Object - * @throws SQLException if a database access error occurs or this method is called on a closed ResultSet - */ - @Override - public Object getObject(final String columnLabel) throws SQLException { - return resultSet.getObject(columnLabel); - } - - /** - * Retrieves the value of the designated column in the current row of this ResultSet object - * as an Object in the Java programming language. The value will be converted to the specified - * Java class using the provided type map. - * - * @param columnIndex the first column is 1, the second is 2, and so on; must be in the range - * [1, number of columns in the current row]. - * @param map a mapping of SQL structured types or SQL DISTINCT types to classes in the Java - * programming language. The type map parameter overrides the default type map - * associated with the connection for this call only. - * @return an Object that represents the SQL value in the specified column, converted to a - * Java object using the provided type map. Returns null if the SQL value is SQL NULL. - * @throws SQLException if a database access error occurs, the columnIndex is out of bounds, - * or if the type map is invalid. - */ - @Override - public Object getObject(final int columnIndex, final Map> map) throws SQLException { - return resultSet.getObject(columnIndex, map); - } - - /** - * Retrieves the value of the specified column as a {@link Ref} object. - * - * @param columnIndex the 1-based index of the column from which the value is to be retrieved - * @return the value of the specified column as a {@link Ref} object, or null if the value is SQL NULL - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public Ref getRef(final int columnIndex) throws SQLException { - return resultSet.getRef(columnIndex); - } - - /** - * Retrieves the Blob object designated by the given column index from the current row of the result set. - * - * @param columnIndex the column index, starting from 1, from which the Blob object is to be retrieved. - * @return the Blob object at the specified column index; may be null if the SQL value is SQL NULL. - * @throws SQLException if a database access error occurs or if this method is called on a closed result set. - */ - @Override - public Blob getBlob(final int columnIndex) throws SQLException { - return resultSet.getBlob(columnIndex); - } - - /** - * Retrieves the CLOB value at the specified column index from the underlying ResultSet. - * - * @param columnIndex the 1-based index of the column from which the CLOB is to be retrieved - * @return the CLOB value from the specified column, or null if the column value is SQL NULL - * @throws SQLException if a database access error occurs or the columnIndex is invalid - */ - @Override - public Clob getClob(final int columnIndex) throws SQLException { - return resultSet.getClob(columnIndex); - } - - /** - * Retrieves an SQL Array object from the specified column index - * of the current row in the ResultSet. - * - * @param columnIndex the index of the column to retrieve the Array from, starting from 1 - * @return an Array object representing the SQL Array value at the specified column index - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public Array getArray(final int columnIndex) throws SQLException { - return resultSet.getArray(columnIndex); - } - - /** - * Retrieves the value of the specified column as an Object, using the given type map for - * custom mappings of SQL user-defined types to Java classes. - * - * @param columnLabel the label for the column from which to retrieve the value - * @param map a map of SQL type names to Java classes for custom type mappings - * @return the value of the specified column as an Object, or null if the value is SQL NULL - * @throws SQLException if a database access error occurs, the columnLabel is not valid, - * or a mapping for a user-defined type is invalid - */ - @Override - public Object getObject(final String columnLabel, final Map> map) throws SQLException { - return resultSet.getObject(columnLabel, map); - } - - /** - * Retrieves the value of the designated column as a Ref object. - * - * @param columnLabel the label for the column specified with the SQL AS clause. - * If the SQL AS clause was not specified, then the label is the name of the column. - * @return a Ref object representing the SQL REF value in the specified column. - * @throws SQLException if a database access error occurs or this method - * is called on a closed result set. - */ - @Override - public Ref getRef(final String columnLabel) throws SQLException { - return resultSet.getRef(columnLabel); - } - - /** - * Retrieves the value of the designated column as a {@code Blob} object. - * - * @param columnLabel the label for the column specified, which is the name of the column as defined in the database - * @return the {@code Blob} object representing the value of the specified column - * @throws SQLException if a database access error occurs or the column label is not valid - */ - @Override - public Blob getBlob(final String columnLabel) throws SQLException { - return resultSet.getBlob(columnLabel); - } - - /** - * Retrieves the CLOB (Character Large Object) value of the designated column - * as specified by the column label. - * - * @param columnLabel the label for the column from which to retrieve the CLOB value - * @return the CLOB object containing the value of the designated column - * @throws SQLException if a database access error occurs or the columnLabel is invalid - */ - @Override - public Clob getClob(final String columnLabel) throws SQLException { - return resultSet.getClob(columnLabel); - } - - /** - * Retrieves the SQL {@code Array} object designated by the specified column label. - * - * @param columnLabel the label for the column from which to retrieve the SQL {@code Array} - * @return the SQL {@code Array} object for the specified column label, or {@code null} if the SQL value is {@code NULL} - * @throws SQLException if the column label is not valid or a database access error occurs - */ - @Override - public Array getArray(final String columnLabel) throws SQLException { - return resultSet.getArray(columnLabel); - } - - /** - * Retrieves the column index for the specified column label in the result set. - * - * @param columnLabel the label of the column for which the index is to be retrieved - * @return the column index corresponding to the specified label - * @throws SQLException if the column label is not valid or a database access error occurs - */ - @Override - public int findColumn(final String columnLabel) throws SQLException { - return resultSet.findColumn(columnLabel); - } - - /** - * Checks if the cursor is positioned before the first row in the result set. - * - * @return true if the cursor is before the first row; false otherwise - * @throws SQLException if a database access error occurs or this method is called on a closed result set - */ - @Override - public boolean isBeforeFirst() throws SQLException { - return resultSet.isBeforeFirst(); - } - - /** - * Checks if the cursor is positioned after the last row in the ResultSet. - * - * @return true if the cursor is after the last row; false otherwise. - * @throws SQLException if a database access error occurs or this method is called on a closed ResultSet. - */ - @Override - public boolean isAfterLast() throws SQLException { - return resultSet.isAfterLast(); - } - - /** - * Checks if the cursor is positioned on the first row of the ResultSet. - * - * @return true if the cursor is on the first row; false otherwise - * @throws SQLException if a database access error occurs or the result set is closed - */ - @Override - public boolean isFirst() throws SQLException { - return resultSet.isFirst(); - } - - /** - * Checks if the current row of the ResultSet object is the last row. - * - * @return true if the current row is the last row; false otherwise - * @throws SQLException if a database access error occurs or this method is called on a closed ResultSet - */ - @Override - public boolean isLast() throws SQLException { - return resultSet.isLast(); - } - - /** - * Moves the cursor of the underlying ResultSet to the position - * before the first row. This is typically used to start iterating - * through the rows of the ResultSet from the beginning. - * - * @throws SQLException if a database access error occurs, - * this method is called on a closed ResultSet, - * or the ResultSet type does not support this operation. - */ - @Override - public void beforeFirst() throws SQLException { - resultSet.beforeFirst(); - } - - /** - * Moves the cursor to the end of the ResultSet, just after the last row. - * This method is typically used to iterate backward through the ResultSet. - * - * @throws SQLException if a database access error occurs or the ResultSet - * is closed. - */ - @Override - public void afterLast() throws SQLException { - resultSet.afterLast(); - } - - /** - * Moves the cursor to the first row of this ResultSet object. - * - * @return true if the cursor is on a valid row; false if there are no rows in the ResultSet. - * @throws SQLException if a database access error occurs or this method is called on a closed ResultSet. - */ - @Override - public boolean first() throws SQLException { - return resultSet.first(); - } - - /** - * Moves the cursor to the last row in the result set. - * - * @return true if the cursor is moved to a valid row; false if there are no rows in the result set. - * @throws SQLException if a database access error occurs or the result set type does not support this operation. - */ - @Override - public boolean last() throws SQLException { - return resultSet.last(); - } - - /** - * Retrieves the current row number from the underlying ResultSet object. - * - * @return the current row number, or 0 if there is no current row - * @throws SQLException if a database access error occurs or this method is called on a closed result set - */ - @Override - public int getRow() throws SQLException { - return resultSet.getRow(); - } - - /** - * Moves the cursor to the given row number in this result set. - * - * @param row the row number to move the cursor to. A positive number moves the cursor - * to the given row number with respect to the beginning, while a negative - * number moves the cursor with respect to the end. - * @return true if the cursor is on a valid row after the move; false if the cursor - * is positioned before the first row or after the last row. - * @throws SQLException if a database access error occurs or the result set is closed. - */ - @Override - public boolean absolute(final int row) throws SQLException { - return resultSet.absolute(row); - } - - /** - * Moves the cursor a relative number of rows, either forward or backward, from its current position. - * Positive values move the cursor forward, and negative values move it backward. - * - * @param rows the number of rows to move the cursor relative to its current position - * @return {@code true} if the cursor is on a valid row after the move; {@code false} if the cursor is positioned before the first row or after the last row - * @throws SQLException if a database access error occurs or the result set is closed - */ - @Override - public boolean relative(final int rows) throws SQLException { - return resultSet.relative(rows); - } - - /** - * Moves the cursor to the previous row in the result set. - * - * @return true if the cursor is moved to a valid row; false if there are no more rows. - * @throws SQLException if a database access error occurs or the result set is closed. - */ - @Override - public boolean previous() throws SQLException { - return resultSet.previous(); - } - - /** - * Retrieves the current fetch direction for the underlying ResultSet. - * - * @return the current fetch direction; this will be one of ResultSet.FETCH_FORWARD, - * ResultSet.FETCH_REVERSE, or ResultSet.FETCH_UNKNOWN. - * @throws SQLException if a database access error occurs or if the ResultSet is closed. - */ - @Override - public int getFetchDirection() throws SQLException { - return resultSet.getFetchDirection(); - } - - /** - * Sets the fetch direction for the ResultSet object to the given direction value. - * The fetch direction gives a hint to the driver about the direction in which - * the rows in the ResultSet will be processed. - * - * @param direction an integer value indicating the fetch direction. - * The allowed values are ResultSet.FETCH_FORWARD, - * ResultSet.FETCH_REVERSE, or ResultSet.FETCH_UNKNOWN. - * @throws SQLException if a database access error occurs or the given - * fetch direction is not supported. - */ - @Override - public void setFetchDirection(final int direction) throws SQLException { - resultSet.setFetchDirection(direction); - } - - /** - * Retrieves the fetch size for the ResultSet associated with this method. - * The fetch size determines how many rows the database fetches at a time from - * the database server when more rows are needed for processing. - * - * @return the fetch size for the ResultSet - * @throws SQLException if a database access error occurs - */ - @Override - public int getFetchSize() throws SQLException { - return resultSet.getFetchSize(); - } - - /** - * Sets the number of rows that should be fetched from the database when more rows are needed. - * This can improve performance by reducing the number of database fetch operations. - * - * @param rows the number of rows to fetch. - * @throws SQLException if a database access error occurs or the parameter value is invalid. - */ - @Override - public void setFetchSize(final int rows) throws SQLException { - resultSet.setFetchSize(rows); - } - - /** - * Retrieves the type of the underlying `ResultSet` object. - * - * @return an integer representing the `ResultSet` type. - * @throws SQLException if a database*/ - @Override - public int getType() throws SQLException { - return resultSet.getType(); - } - - /** - * Retrieves the concurrency mode of the result set. - * - * @return an integer representing the concurrency mode of the result set. - * @throws SQLException if a database access error occurs or the result set is closed. - */ - @Override - public int getConcurrency() throws SQLException { - return resultSet.getConcurrency(); - } - - /** - * Checks if the current row of the result set has been updated. - * - * @return true if the current row has been updated and the result set type is a type that detects changes; false otherwise - * @throws SQLException if a database access error occurs or the method is called on a closed result set - */ - @Override - public boolean rowUpdated() throws SQLException { - return resultSet.rowUpdated(); - } - - /** - * Checks whether the current row in the ResultSet was successfully inserted. - * - * @return true if the current row was inserted, false otherwise - * @throws SQLException if a database access error occurs - */ - @Override - public boolean rowInserted() throws SQLException { - return resultSet.rowInserted(); - } - - /** - * Checks whether the current row in the ResultSet has been deleted. - * - * This method provides a way to determine if the current row, positioned - * in the ResultSet, has been deleted from the database. It relies on the - * underlying ResultSet's implementation of the rowDeleted method. - * - * @return true if the current row has been deleted and false otherwise - * @throws SQLException if a database access error occurs - */ - @Override - public boolean rowDeleted() throws SQLException { - return resultSet.rowDeleted(); - } - - /** - * Updates the designated column with a SQL NULL value. - * - * @param columnIndex the index of the column to update. The first column is 1, the second is 2, and so on. - * @throws SQLException if a database access error occurs or if the columnIndex is invalid. - */ - @Override - public void updateNull(final int columnIndex) throws SQLException { - resultSet.updateNull(columnIndex); - } - - /** - * Updates the designated column with a boolean value. The update is applied - * to the ResultSet object and can be persisted into the underlying database - * by calling the updateRow method. - * - * @param columnIndex the one-based index of the column to update - * @param x the new boolean value to set in the specified column - * @throws SQLException if the column index is invalid, the ResultSet is closed, - * or a database access error occurs - */ - @Override - public void updateBoolean(final int columnIndex, final boolean x) throws SQLException { - resultSet.updateBoolean(columnIndex, x); - } - - /** - * Updates the designated column with a new byte value. - * - * @param columnIndex the index of the column, starting from 1, where the byte value will be updated - * @param x the new byte value to set in the specified column - * @throws SQLException if a database access error occurs or if this method is called on a closed result set - */ - @Override - public void updateByte(final int columnIndex, final byte x) throws SQLException { - resultSet.updateByte(columnIndex, x); - } - - /** - * Updates the designated column with a short value. - * The update is made to the current row of the ResultSet object. - * - * @param columnIndex the index of the column to update, where the first column is 1 - * @param x the new column value as a short - * @throws SQLException if a database access error occurs, the ResultSet is in read-only mode, - * or the columnIndex is not valid - */ - @Override - public void updateShort(final int columnIndex, final short x) throws SQLException { - resultSet.updateShort(columnIndex, x); - } - - /** - * Updates the designated column with an int value. The updater methods are used to update column - * values in the current row or the insert row. - * - * @param columnIndex the column index (1-based) of the column to update - * @param x the new column value - * @throws SQLException if a database access error occurs or the columnIndex is invalid - */ - @Override - public void updateInt(final int columnIndex, final int x) throws SQLException { - resultSet.updateInt(columnIndex, x); - } - - /** - * Updates the designated column with a long value. - * The updater methods are used to update column values in the current row or the insert row. - * - * @param columnIndex the index of the column to update, starting from 1 - * @param x the new long value to be set in the column - * @throws SQLException if a database access error occurs or if the result set is read-only - */ - @Override - public void updateLong(final int columnIndex, final long x) throws SQLException { - resultSet.updateLong(columnIndex, x); - } - - /** - * Updates the designated column with a float value. - * The updater methods are used to update column values in the current row or the insert row. - * - * @param columnIndex the index of the column to update, starting from 1 - * @param x the new column value as a float - * @throws SQLException if a database access error occurs or if the method is called on a closed result set - */ - @Override - public void updateFloat(final int columnIndex, final float x) throws SQLException { - resultSet.updateFloat(columnIndex, x); - } - - /** - * Updates the designated column with a double value. The column is specified by its index. - * This method must be called on an updatable ResultSet, and the change is only reflected in - * the ResultSet until updateRow() is called to propagate the change to the underlying database. - * - * @param columnIndex the first column is 1, the second is 2, and so on - * @param x the new column value as a double - * @throws SQLException if a database access error occurs or if the column index is not valid - */ - @Override - public void updateDouble(final int columnIndex, final double x) throws SQLException { - resultSet.updateDouble(columnIndex, x); - } - - /** - * Updates the designated column with a BigDecimal value. - * The update is made to the current row of the result set. - * - * @param columnIndex the first column is 1, the second is 2, and so on. - * @param x the new column value as a BigDecimal. A null value indicates - * SQL NULL. - * @throws SQLException if a database access error occurs, this method is - * called on a closed result set, or the ResultSet is - * in an invalid state. - */ - @Override - public void updateBigDecimal(final int columnIndex, final BigDecimal x) throws SQLException { - resultSet.updateBigDecimal(columnIndex, x); - } - - /** - * Updates the designated column with a provided string value. - * This method must be called on a valid column index within the ResultSet. - * - * @param columnIndex the index of the column to update, starting from 1 - * @param x the new string value to set; can be null - * @throws SQLException if a database access error occurs or if the provided index is invalid - */ - @Override - public void updateString(final int columnIndex, final String x) throws SQLException { - resultSet.updateString(columnIndex, x); - } - - /** - * Updates the designated column with a byte array value. The updated value - * will be written to the database when updateRow, insertRow, or deleteRow - * is called. - * - * @param columnIndex the first column is 1, the second is 2, and so on - * @param x the new byte array value for the specified column - * @throws SQLException if the columnIndex is invalid; if a database access - * error occurs; if this method is called on a closed result set; - * or if this method is called in a read-only result set - */ - @Override - public void updateBytes(final int columnIndex, final byte[] x) throws SQLException { - resultSet.updateBytes(columnIndex, x); - } - - /** - * Updates the designated column with a Date object. - * The updater methods are used to update column values in the current row or the insert row. - * - * @param columnIndex the index of the column to update (1-based) - * @param x the new column value as a Date object - * @throws SQLException if a database access error occurs or if the column index is invalid - */ - @Override - public void updateDate(final int columnIndex, final Date x) throws SQLException { - resultSet.updateDate(columnIndex, x); - } - - /** - * Updates the designated column with a {@code Time} value. - * The update is made in the current row of the ResultSet. - * - * @param columnIndex the first column is 1, the second is 2, and so on - * @param x the new column value; must be a {@code Time} object - * @throws SQLException if the column index is invalid, if a database access error occurs, - * or if the ResultSet is in read-only mode - */ - @Override - public void updateTime(final int columnIndex, final Time x) throws SQLException { - resultSet.updateTime(columnIndex, x); - } - - /** - * Updates the designated column with a {@link Timestamp} value. - * - * @param columnIndex the first column is 1, the second is 2, and so on. - * @param x the new column value; can be null to update the column with SQL NULL. - * @throws SQLException if the column index is invalid, this method is called on a closed result set, - * or a database access error occurs. - */ - @Override - public void updateTimestamp(final int columnIndex, final Timestamp x) throws SQLException { - resultSet.updateTimestamp(columnIndex, x); - } - - /** - * Updates the designated column with an ASCII stream value. - * The data in the stream can be read and is then written to the database. - * - * @param columnIndex the index of the column to update, starting from 1 - * @param x the input stream containing the ASCII data to set - * @param length the number of bytes in the input stream to write to the column - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public void updateAsciiStream(final int columnIndex, final InputStream x, final int length) throws SQLException { - resultSet.updateAsciiStream(columnIndex, x, length); - } - - /** - * Updates the designated column with a binary stream value. - * - * @param columnIndex the index of the column to update, where the first column is 1 - * @param x the InputStream containing the binary data to set in the column - * @param length the number of bytes in the InputStream to read and write to the column - * @throws SQLException if a database access error occurs or the columnIndex is invalid - */ - @Override - public void updateBinaryStream(final int columnIndex, final InputStream x, final int length) throws SQLException { - resultSet.updateBinaryStream(columnIndex, x, length); - } - - /** - * Updates the designated column with a character stream value. The data will be read from - * the provided Reader object and written to the database. The number of characters to be written - * is specified by the length parameter. - * - * @param columnIndex the index of the column to be updated, starting from 1 - * @param x the Reader object containing the character data to be written - * @param length the number of characters to be written from the Reader - * @throws SQLException if a database access error occurs or if the columnIndex is invalid - */ - @Override - public void updateCharacterStream(final int columnIndex, final Reader x, final int length) throws SQLException { - resultSet.updateCharacterStream(columnIndex, x, length); - } - - /** - * Updates the designated column with an Object value. The scale or length - * is used for certain types of updates such as updating a numeric value - * or strings where precision or length needs to be specified. - * - * @param columnIndex the index of the column (starting at 1) to be updated - * @param x the new value for the column - * @param scaleOrLength for numeric and string types, this is the precision or - * length to be used; otherwise, ignored - * @throws SQLException if a database access error occurs or if this method - * is called on a closed result set - */ - @Override - public void updateObject(final int columnIndex, final Object x, final int scaleOrLength) throws SQLException { - resultSet.updateObject(columnIndex, x, scaleOrLength); - } - - /** - * Updates the value of the designated column with the given object. - * - * @param columnIndex the index of the column to update, starting from 1 - * @param x the new value for the column, as an Object - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public void updateObject(final int columnIndex, final Object x) throws SQLException { - resultSet.updateObject(columnIndex, x); - } - - /** - * Updates the designated column with a null value. This method is typically used - * when updating database records to explicitly set a column to NULL. - * - * @param columnLabel the label for the column specified with the SQL AS clause. - * If the SQL AS clause was not specified, the column name is used. - * @throws SQLException if a database access error occurs or the result set is not - * updatable. - */ - @Override - public void updateNull(final String columnLabel) throws SQLException { - resultSet.updateNull(columnLabel); - } - - /** - * Updates the designated column with a boolean value. - * - * @param columnLabel the label for the column specified to be updated - * @param x the new boolean value to update the column with - * @throws SQLException if a database access error occurs or the columnLabel is not valid - */ - @Override - public void updateBoolean(final String columnLabel, final boolean x) throws SQLException { - resultSet.updateBoolean(columnLabel, x); - } - - /** - * Updates the designated column with a byte value. The update is applied to the current row - * of the ResultSet object. - * - * @param columnLabel the label for the column to be updated. It must match the column name as - * defined in the database table. - * @param x the new byte value that will be assigned to the specified column. - * @throws SQLException if a database access error occurs, the column label is not valid, or - * the ResultSet is in read-only mode. - */ - @Override - public void updateByte(final String columnLabel, final byte x) throws SQLException { - resultSet.updateByte(columnLabel, x); - } - - /** - * Updates the designated column with a short value. - * The updated value is not immediately written to the database but is cached in the ResultSet until {@code updateRow()} is called. - * - * @param columnLabel the label for the column to be updated - * @param x the new column value as a short - * @throws SQLException if a database access error occurs, this method is called on a closed ResultSet, - * or if the columnLabel is not valid - */ - @Override - public void updateShort(final String columnLabel, final short x) throws SQLException { - resultSet.updateShort(columnLabel, x); - } - - /** - * Updates the designated column with the specified integer value. - * This method is used to update the value of a column in the current row - * of the ResultSet object. The column is specified by its label. - * - * @param columnLabel the label for the column to be updated - * @param x the new integer value for the column - * @throws SQLException if a database access error occurs or the result set - * is not updatable - */ - @Override - public void updateInt(final String columnLabel, final int x) throws SQLException { - resultSet.updateInt(columnLabel, x); - } - - /** - * Updates the designated column with a specified long value. The updater methods are used - * to update column values in the current row or the insert row*/ - @Override - public void updateLong(final String columnLabel, final long x) throws SQLException { - resultSet.updateLong(columnLabel, x); - } - - /** - * Updates the designated column with a float value. The update is applied to - * the current row of the ResultSet object. - * - * @param columnLabel the label for the column that is to be updated - * @param x the new column value as a float - * @throws SQLException if an error occurs while updating the column or if the - * ResultSet is in an invalid state for the update - */ - @Override - public void updateFloat(final String columnLabel, final float x) throws SQLException { - resultSet.updateFloat(columnLabel, x); - } - - /** - * Updates the designated column with a specified double value. - * - * @param columnLabel the label for the column specified, which is the name of the column - * @param x the new column value as a double - * @throws SQLException if a database access error occurs, the result set is closed, - * or the columnLabel is not valid - */ - @Override - public void updateDouble(final String columnLabel, final double x) throws SQLException { - resultSet.updateDouble(columnLabel, x); - } - - /** - * Updates the designated column with a {@code BigDecimal} value. - * The update is made to the underlying database as well as to the - * {@code ResultSet} object. - * - * @param columnLabel the label of the column to update - * @param x the new {@code BigDecimal} value to assign to the column; - * can be {@code null} - * @throws SQLException if a database access error occurs - */ - @Override - public void updateBigDecimal(final String columnLabel, final BigDecimal x) throws SQLException { - resultSet.updateBigDecimal(columnLabel, x); - } - - /** - * Updates the designated column with a new String value. - * The update is applicable to the current row of the ResultSet. - * - * @param columnLabel the label for the column to be updated - * @param x the new String value to update the column with - * @throws SQLException if a database access error occurs, - * the columnLabel is not valid or the ResultSet is in an invalid state - */ - @Override - public void updateString(final String columnLabel, final String x) throws SQLException { - resultSet.updateString(columnLabel, x); - } - - /** - * Updates the designated column with a byte array value. - * The updateBytes method should be used when updating columns in - * a ResultSet that is updateable. - * - * @param columnLabel the label for the column to be updated - * @param x the new column value stored as a byte array - * @throws SQLException if a database access error occurs or the ResultSet cannot be updated - */ - @Override - public void updateBytes(final String columnLabel, final byte[] x) throws SQLException { - resultSet.updateBytes(columnLabel, x); - } - - /** - * Updates the designated column with a Date value. This method is used to update - * the value of a specified column in the current row of the ResultSet with a Date object. - * - * @param columnLabel the label for the column specified with the SQL AS clause. - * If the SQL AS clause was not specified, the label is the name of the column. - * @param x the new Date value to update the specified column with. This value can be null. - * @throws SQLException if a database access error occurs or the ResultSet is in read-only mode. - */ - @Override - public void updateDate(final String columnLabel, final Date x) throws SQLException { - resultSet.updateDate(columnLabel, x); - } - - /** - * Updates the designated column with a {@code Time} value. - * The update is made to the current row of the {@link ResultSet} object. - * - * @param columnLabel the label of the column to be updated - * @param x the new column {@code Time} value - * @throws SQLException if a database access error occurs or the columnLabel - * is not valid - */ - @Override - public void updateTime(final String columnLabel, final Time x) throws SQLException { - resultSet.updateTime(columnLabel, x); - } - - /** - * Updates the designated column with a Timestamp value. - * This method updates the column denoted by the specified column label - * in the current row of this ResultSet object. - * - * @param columnLabel the label for the column to be updated - * @param x the new column value as a Timestamp object; may be null - * @throws SQLException if a database access error occurs, the ResultSet is closed, - * or if the provided column label does not exist - */ - @Override - public void updateTimestamp(final String columnLabel, final Timestamp x) throws SQLException { - resultSet.updateTimestamp(columnLabel, x); - } - - /** - * Updates the designated column with an ASCII stream value. - * The input stream must contain ASCII characters. The stream must be fully read before - * setting the value to the designated column. - * - * @param columnLabel the label for the column to be updated - * @param x the input stream containing the ASCII data - * @param length the number of bytes in the input stream - * @throws SQLException if a database access error occurs or the columnLabel is not valid - */ - @Override - public void updateAsciiStream(final String columnLabel, final InputStream x, final int length) throws SQLException { - resultSet.updateAsciiStream(columnLabel, x, length); - } - - /** - * Updates the designated column with a binary input stream containing the specified number of bytes. - * This method is used to store binary data into a column. - * - * @param columnLabel the label for the column specified with the update - * @param x the InputStream object that contains the binary data to be written - * @param length the number of bytes in the InputStream to be written to the column - * @throws SQLException if a database access error occurs or the columnLabel is not valid - */ - @Override - public void updateBinaryStream(final String columnLabel, final InputStream x, final int length) throws SQLException { - resultSet.updateBinaryStream(columnLabel, x, length); - } - - /** - * Updates the designated column with a character stream value. The character stream will have - * a specified length in characters. - * - * @param columnLabel the label of the column to update - * @param reader the java.io.Reader object that contains the character stream - * @param length the number of characters in the input stream - * @throws SQLException if a database access error occurs or the value is invalid - */ - @Override - public void updateCharacterStream(final String columnLabel, final Reader reader, final int length) throws SQLException { - resultSet.updateCharacterStream(columnLabel, reader, length); - } - - /** - * Updates the designated column with an object value. The update is applied to - * the specified column in the current row of this ResultSet object. - * - * @param columnLabel the label for the column specified with the update - * @param x the new column value, which must be an instance of a class supported by the JDBC driver - * or null to set the column value to SQL NULL - * @param scaleOrLength for an input parameter of SQL type DECIMAL or NUMERIC, this is the - * number of digits after the decimal point. For Java Object types - * InputStream and Reader, this is the length of the data in the stream or reader. - * For all other types, this value will be ignored. - * @throws SQLException if a database access error occurs or this method is called on a closed ResultSet - */ - @Override - public void updateObject(final String columnLabel, final Object x, final int scaleOrLength) throws SQLException { - resultSet.updateObject(columnLabel, x, scaleOrLength); - } - - /** - * Updates the designated column with an Object value. - * The update is applied to the current row of the ResultSet, and will be written to the database - * when the ResultSet is updated. - * - * @param columnLabel the label of the column to be updated - * @param x the new column value to be set, which can be any object type - * @throws SQLException if a database access error occurs or if the columnLabel is not valid - */ - @Override - public void updateObject(final String columnLabel, final Object x) throws SQLException { - resultSet.updateObject(columnLabel, x); - } - - /** - * Inserts the current row into the database. - * - * This method delegates the call to {@link ResultSet#insertRow()}. - * The method inserts the contents of the insert row into the database. - * It must be called while the cursor is positioned on the insert row. - * After the insertion, the cursor will remain positioned on the insert row. - * - * @throws SQLException if a database access error occurs or if this method - * is called when the cursor is not on the insert row. - */ - @Override - public void insertRow() throws SQLException { - resultSet.insertRow(); - } - - /** - * Updates the current row in the database using the current values of the - * ResultSet. This method writes any changes made to the result set to - * the database. - * - * @throws SQLException if a database access error occurs, the ResultSet - * is in read-only mode, or if this method is called on a - * ResultSet that is not positioned on a valid row. - */ - @Override - public void updateRow() throws SQLException { - resultSet.updateRow(); - } - - /** - * Deletes the current row from the database. - * This method removes the current row in the ResultSet object - * and the corresponding row in the database. - * - * @throws SQLException if a database access error occurs, - * the current row is not valid, or the ResultSet object is - * not updatable. - */ - @Override - public void deleteRow() throws SQLException { - resultSet.deleteRow(); - } - - /** - * Refreshes the current row of the ResultSet object to reflect the most recent - * changes made to the database. This method is particularly useful when - * concurrent updates are made to the underlying database, allowing the ResultSet - * to synchronize its data with the latest state of the database row. - * - * @throws SQLException if a database access error occurs or if the ResultSet - * is closed. - */ - @Override - public void refreshRow() throws SQLException { - resultSet.refreshRow(); - } - - /** - * Cancels the updates made to the current row in this ResultSet object. - * - * If the cancelRowUpdates method is called, the updates made to the current row - * will be discarded and no changes will be applied when the ResultSet is updated. - * - * This method delegates the call to the wrapped ResultSet's cancelRowUpdates method. - * - * @throws SQLException if a database access error occurs or this method is called - * on a closed ResultSet. - */ - @Override - public void cancelRowUpdates() throws SQLException { - resultSet.cancelRowUpdates(); - } - - /** - * Moves the cursor to the insert row of the ResultSet object. - * The insert row is a special row associated with a ResultSet - * object that is used as a staging ground for building a row - * to be inserted. Only columns with a defined value can be updated - * when on the insert row. - * - * This method provides a convenient way to prepare a row for insert - * operations. After setting the desired column values using the - * appropriate updater methods, the row can be committed to the - * database using the `insertRow` method of the ResultSet. - * - * @throws SQLException if a database access error occurs or - * if this method is called on a closed ResultSet. - */ - @Override - public void moveToInsertRow() throws SQLException { - resultSet.moveToInsertRow(); - } - - /** - * Moves the cursor to the remembered cursor position, usually the position - * where the cursor was located prior to calling the {@code moveToInsertRow} method. - * This method is typically used when working with updatable result sets, allowing the - * cursor to return to its previous position after inserting a row. - * - * @throws SQLException if a database access error occurs or this method is - * called on a ResultSet object that is not updatable. - */ - @Override - public void moveToCurrentRow() throws SQLException { - resultSet.moveToCurrentRow(); - } - - /** - * Retrieves the Statement object that produced this ResultSet object. - * - * @return the Statement object that produced this ResultSet or null if the result set was generated - * by a DatabaseMetaData method or if this method is called on a closed result set. - * @throws SQLException if a database access error occurs or this method is called on a closed result set. - */ - @Override - public Statement getStatement() throws SQLException { - return resultSet.getStatement(); - } - - /** - * Updates the designated column with an ASCII stream value. - * The data will be read from the provided InputStream and should match the specified length. - * This method can be used to update a column in the current row of a ResultSet object. - * - * @param columnIndex the index of the column to update, starting from 1 - * @param x the InputStream object containing the ASCII stream data - * @param length the length of the ASCII stream in bytes - * @throws SQLException if a database access error occurs or the ResultSet is not updatable - */ - @Override - public void updateAsciiStream(final int columnIndex, final InputStream x, final long length) throws SQLException { - resultSet.updateAsciiStream(columnIndex, x, length); - } - - /** - * Updates the designated column with a binary stream value. The data will be read from the given - * InputStream object starting from the current position to the specified length. The stream must - * provide at least the number of bytes specified by the length parameter. - * - * @param columnIndex the index of the column to update (1-based index) - * @param x the InputStream containing the binary data - * @param length the number of bytes to write from the InputStream - * @throws SQLException if a database access error occurs or if any argument is invalid - */ - @Override - public void updateBinaryStream(final int columnIndex, final InputStream x, final long length) throws SQLException { - resultSet.updateBinaryStream(columnIndex, x, length); - } - - /** - * Updates the designated column with a character stream value. - * The data will be read from the provided Reader object. - * - * @param columnIndex the 1-based index of the column to update - * @param x the Reader object that contains the new character stream value - * @param length the number of characters in the stream - * @throws SQLException if a database access error occurs, the column index is out of bounds, - * or if the provided Reader is null - */ - @Override - public void updateCharacterStream(final int columnIndex, final Reader x, final long length) throws SQLException { - resultSet.updateCharacterStream(columnIndex, x, length); - } - - /** - * Updates the designated column with an ASCII stream value. The stream must contain - * ASCII characters and is read to the specified number of characters. If the designated - * column does not support ASCII stream updates, a SQLException will be thrown. - * - * @param columnLabel the label of the column to be updated - * @param x the InputStream containing the ASCII data - * @param length the number of bytes to read from the InputStream - * @throws SQLException if a database access error occurs, if the columnLabel does not exist, - * or if this method is called on a closed result set - */ - @Override - public void updateAsciiStream(final String columnLabel, final InputStream x, final long length) throws SQLException { - resultSet.updateAsciiStream(columnLabel, x, length); - } - - /** - * Updates the designated column with a binary stream value. - * The data will be read from the supplied {@code InputStream} and written to the column, - * according to the specified length. - * - * @param columnLabel the label for the column to be updated - * @param x the {@code InputStream} object that contains the new column value - * @param length the number of bytes in the stream to read - * @throws SQLException if a database access error occurs or if the columnLabel is not valid - */ - @Override - public void updateBinaryStream(final String columnLabel, final InputStream x, final long length) throws SQLException { - resultSet.updateBinaryStream(columnLabel, x, length); - } - - /** - * Updates the designated column with a character stream value. - * The data in the stream will have the specified length. - * - * @param columnLabel the label for the column name - * @param reader the java.io.Reader object that contains the data to set the column value to - * @param length the number of characters in the stream - * @throws SQLException if the columnLabel is not valid, a database access error occurs, - * the result set is closed, or if this method is called on a read-only result set - */ - @Override - public void updateCharacterStream(final String columnLabel, final Reader reader, final long length) throws SQLException { - resultSet.updateCharacterStream(columnLabel, reader, length); - } - - /** - * Updates the designated column with a {@link Blob} value. - * - * The updateBlob method updates the current row's column with the - * specified Blob object. The update is not persisted in the database - * until the {@code updateRow()} method is called. - * - * @param columnIndex the index of the column to update, starting from 1 - * @param x the new Blob value to assign to the column - * @throws SQLException if a database access error occurs or the result set - * is not updatable - */ - @Override - public void updateBlob(final int columnIndex, final Blob x) throws SQLException { - resultSet.updateBlob(columnIndex, x); - } - - /** - * Updates the designated column with a Blob value. The updater methods are - * used to update column values in the current row or the insert row. The - * update is not applied to the database until the method `updateRow` is called. - * - * @param columnLabel the label for the column specified with the SQL query. - * @param x the Blob object that contains the data to set the value in the specified column. - * @throws SQLException if a database access error occurs or this method is - * called on a closed ResultSet. - */ - @Override - public void updateBlob(final String columnLabel, final Blob x) throws SQLException { - resultSet.updateBlob(columnLabel, x); - } - - /** - * Updates the designated column with a Clob value. The column is specified by its index, - * and the value is provided as a Clob object. This method updates the Clob value on the - * underlying database structure. - * - * @param columnIndex the index of the column to update, starting from 1. - * @param x the Clob object containing the new value to set for the specified column. - * @throws SQLException if a database access error occurs or the operation is not supported. - */ - @Override - public void updateClob(final int columnIndex, final Clob x) throws SQLException { - resultSet.updateClob(columnIndex, x); - } - - /** - * Updates the designated column with a Clob value. The updater methods are used to update column - * values in the result set, which can then be updated in the underlying database. - * - * @param columnLabel the label for the column specified in the SQL query - * @param x the Clob value to update the column with - * @throws SQLException if a database access error occurs or the result set is in read-only mode - */ - @Override - public void updateClob(final String columnLabel, final Clob x) throws SQLException { - resultSet.updateClob(columnLabel, x); - } - - /** - * Updates the designated column with an Array value. - * - * @param columnIndex the index of the column to be updated, where the first column is 1 - * @param x the new Array value to update the column with - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public void updateArray(final int columnIndex, final Array x) throws SQLException { - resultSet.updateArray(columnIndex, x); - } - - /** - * Updates the designated column with an Array value. - * - * @param columnLabel the label for the column to be updated - * @param x the Array object to update the column with - * @throws SQLException if a database access error occurs or the columnLabel is invalid - */ - @Override - public void updateArray(final String columnLabel, final Array x) throws SQLException { - resultSet.updateArray(columnLabel, x); - } - - /** - * Retrieves the RowId object that corresponds to the specified column index in the result set. - * - * @param columnIndex the column index, starting from 1, for which the RowId is to be retrieved - * @return the RowId value for the specified column index - * @throws SQLException if a database access error occurs or the columnIndex is invalid - */ - @Override - public RowId getRowId(final int columnIndex) throws SQLException { - return resultSet.getRowId(columnIndex); - } - - /** - * Retrieves the RowId object corresponding to the specified column label. - * - * @param columnLabel the label for the column from which to retrieve the RowId - * @return the RowId object for the specified column - * @throws SQLException if a database access error occurs or the column label is invalid - */ - @Override - public RowId getRowId(final String columnLabel) throws SQLException { - return resultSet.getRowId(columnLabel); - } - - /** - * Updates the designated column with a RowId value. - * The updateRowId method provides the capability to update the column with a RowId object - * which represents the SQL ROWID data type. The update is performed for the current row - * of the ResultSet. - * - * @param columnIndex the 1-based index of the column to be updated - * @param x the RowId object containing the new value for the column - * @throws SQLException if a database access error occurs or the result set is not updatable - */ - @Override - public void updateRowId(final int columnIndex, final RowId x) throws SQLException { - resultSet.updateRowId(columnIndex, x); - } - - /** - * Updates the designated column with a new RowId value. - * - * @param columnLabel the label for the column specified by the SQL AS clause. - * If the SQL AS clause was not specified, the name of the column is used. - * @param x the new RowId value to update in the specified column - * @throws SQLException if a database access error occurs or the method is called on a closed ResultSet - */ - @Override - public void updateRowId(final String columnLabel, final RowId x) throws SQLException { - resultSet.updateRowId(columnLabel, x); - } - - /** - * Retrieves the current holdability of ResultSet objects created using this method. - * - * @return an integer representing the holdability of ResultSet objects. The value is - * either ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT. - * @throws SQLException if a database access error occurs. - */ - @Override - public int getHoldability() throws SQLException { - return resultSet.getHoldability(); - } - - /** - * Checks if the {@code ResultSet} is closed. - * - * @return {@code true} if the {@code ResultSet} is closed; {@code false} otherwise. - * @throws SQLException if a database access error occurs. - */ - @Override - public boolean isClosed() throws SQLException { - return resultSet.isClosed(); - } - - /** - * Updates the designated column with a String value. The column index specifies - * the column to be updated, and the String value provided will be stored in the - * appropriate column of the underlying database. - * - * @param columnIndex the first column is 1, the second is 2, and so on - * @param nString the new value for the designated column. Can be null. - * @throws SQLException if a database access error occurs or this method is - * called on a closed ResultSet - */ - @Override - public void updateNString(final int columnIndex, final String nString) throws SQLException { - resultSet.updateNString(columnIndex, nString); - } - - /** - * Updates the designated column with the given string value. The updateNString method should - * be used when the column stores a national character set value. - * - * @param columnLabel the label for the column to be updated - * @param nString the new column value of type String - * @throws SQLException if a database access error occurs or if the method is called on a closed result set - */ - @Override - public void updateNString(final String columnLabel, final String nString) throws SQLException { - resultSet.updateNString(columnLabel, nString); - } - - /** - * Updates the designated column with a given NClob value. - * Updates the NClob object in the ResultSet to reflect changes. - * - * @param columnIndex the column index in the ResultSet, starting at 1, which needs to be updated - * @param nClob the NClob object that holds the new value to assign to the column - * @throws SQLException if a database access error occurs or the ResultSet is in a read-only state - */ - @Override - public void updateNClob(final int columnIndex, final NClob nClob) throws SQLException { - resultSet.updateNClob(columnIndex, nClob); - } - - /** - * Updates the designated column with a given NClob object. The column is specified by - * its label, and the input NClob object will be used to update the value in the - * ResultSet. This method can be used to update NClob data in a database. - * - * @param columnLabel the label for the column to be updated - * @param nClob the NClob object containing the data to update the column with - * @throws SQLException if a database access error occurs or this method is called - * on a closed ResultSet - */ - @Override - public void updateNClob(final String columnLabel, final NClob nClob) throws SQLException { - resultSet.updateNClob(columnLabel, nClob); - } - - /** - * Retrieves the value of the specified column as a {@code NClob} object. - * - * @param columnIndex the index of the column from which the value is to be retrieved, - * starting at 1 for the first column. - * @return the {@code NClob} object representing the value of the specified column, - * or {@code null} if the column contains SQL {@code NULL}. - * @throws SQLException if a database access error occurs or if the column index is invalid. - */ - @Override - public NClob getNClob(final int columnIndex) throws SQLException { - return resultSet.getNClob(columnIndex); - } - - /** - * Retrieves the value of the designated column as a {@link NClob} object. - * - * @param columnLabel the label for the column specified with the SQL AS clause. - * If the SQL AS clause was not specified, then the label is the name of the column. - * @return the value of the designated column as a {@link NClob} object; - * if the value is SQL NULL, the method returns null. - * @throws SQLException if a database access error occurs or this method is called on a closed result set. - */ - @Override - public NClob getNClob(final String columnLabel) throws SQLException { - return resultSet.getNClob(columnLabel); - } - - /** - * Retrieves the value of the designated column in the current row of this - * ResultSet object as a SQLXML object. - * - * @param columnIndex the column index, starting from 1 for the first column - * @return the SQLXML value of the specified column in the current row - * @throws SQLException if a database access error occurs or the column index is not valid - */ - @Override - public SQLXML getSQLXML(final int columnIndex) throws SQLException { - return resultSet.getSQLXML(columnIndex); - } - - /** - * Retrieves the value of the designated column as a {@code SQLXML} object. - * - * @param columnLabel the label for the column specified in the query. - * @return the {@code SQLXML} object representing the SQL XML value of the specified column. - * @throws SQLException if there is an error accessing the SQL data or if the column does not support SQLXML values. - */ - @Override - public SQLXML getSQLXML(final String columnLabel) throws SQLException { - return resultSet.getSQLXML(columnLabel); - } - - /** - * Updates the designated column with the given SQLXML value. - * - * @param columnIndex the first column is 1, the second is 2, and so on. - * @param xmlObject the SQLXML object representing the XML value to update the column with. - * @throws SQLException if a database access error occurs or if the columnIndex is invalid. - */ - @Override - public void updateSQLXML(final int columnIndex, final SQLXML xmlObject) throws SQLException { - resultSet.updateSQLXML(columnIndex, xmlObject); - } - - /** - * Updates the designated column with an SQLXML value. The update is performed - * on the current row of the ResultSet. - * - * @param columnLabel the label for the column specified with the SQL XML data type. - * @param xmlObject the SQLXML object containing the data to set in the specified column. - * @throws SQLException if an error occurs while updating the SQLXML value or if the ResultSet is in read-only mode. - */ - @Override - public void updateSQLXML(final String columnLabel, final SQLXML xmlObject) throws SQLException { - resultSet.updateSQLXML(columnLabel, xmlObject); - } - - /** - * Updates the designated column with a character stream value. The data will be read - * from the provided Reader object and should have a specified length. - * - * @param columnIndex the column index (1-based) indicating the column to be updated - * @param x the Reader object that contains the new character stream data - * @param length the number of characters in the stream to be read - * @throws SQLException if a database access error occurs or the columnIndex is invalid - */ - @Override - public void updateNCharacterStream(final int columnIndex, final Reader x, final long length) throws SQLException { - resultSet.updateNCharacterStream(columnIndex, x, length); - } - - /** - * Updates the designated column with a character stream value. - * The data will be read from the provided Reader and will have the specified length. - * - * @param columnLabel the label for the column to update - * @param reader the java.io.Reader object from which the data will be read - * @param length the length of the stream in characters - * @throws SQLException if a database access error occurs or the column label is invalid - */ - @Override - public void updateNCharacterStream(final String columnLabel, final Reader reader, final long length) throws SQLException { - resultSet.updateNCharacterStream(columnLabel, reader, length); - } - - /** - * Updates the designated column with a character stream value. The data will be read from the provided - * Reader object and used to update the column indicated by the columnIndex parameter. - * - * @param columnIndex the index of the column to update, where the first column is 1 - * @param x the Reader object that contains the new character stream data - * @throws SQLException if a database access error occurs or the result set is in a read-only mode - */ - @Override - public void updateNCharacterStream(final int columnIndex, final Reader x) throws SQLException { - resultSet.updateNCharacterStream(columnIndex, x); - } - - /** - * Updates the designated column with a character stream value, which will then - * be written to the database. The column specified by the given label will be updated - * with the data provided by the Reader object. - * - * @param columnLabel the label for the column that needs to be updated. - * @param reader the java.io.Reader object containing the data to set the column value. - * @throws SQLException if a database access error occurs or the columnLabel is invalid. - */ - @Override - public void updateNCharacterStream(final String columnLabel, final Reader reader) throws SQLException { - resultSet.updateNCharacterStream(columnLabel, reader); - } - - /** - * Updates the designated column with a binary stream value, which will have - * the specified number of bytes. The data will be read from the provided - * {@code InputStream}. - * - * @param columnIndex the first column is 1, the second is 2, ... - * @param inputStream the {@code InputStream} object containing the binary data - * @param length the number of bytes in the binary data - * @throws SQLException if a database access error occurs or if the column - * index is invalid - */ - @Override - public void updateBlob(final int columnIndex, final InputStream inputStream, final long length) throws SQLException { - resultSet.updateBlob(columnIndex, inputStream, length); - } - - /** - * Updates the designated column with an InputStream value, which will be written to the database as a Blob. - * - * @param columnLabel the label for the column to be updated - * @param inputStream the InputStream containing the Blob data - * @param length the number of bytes in the InputStream - * @throws SQLException if a database access error occurs or the columnLabel is invalid - */ - @Override - public void updateBlob(final String columnLabel, final InputStream inputStream, final long length) throws SQLException { - resultSet.updateBlob(columnLabel, inputStream, length); - } - - /** - * Updates the designated column with a binary stream value. - * The input stream is used to supply the binary data for the value to be set in the column. - * - * @param columnIndex the first column is 1, the second is 2, and so on - * @param inputStream the InputStream containing the binary data to set - * @throws SQLException if the columnIndex is invalid, if a database access error occurs, - * or if this method is called on a closed result set - */ - @Override - public void updateBlob(final int columnIndex, final InputStream inputStream) throws SQLException { - resultSet.updateBlob(columnIndex, inputStream); - } - - /** - * Updates the designated column with an InputStream value, which will be - * set as a BLOB in the underlying database. - * - * @param columnLabel the label for the column whose value will be set - * @param inputStream the InputStream containing the binary data to set as a BLOB - * @throws SQLException if a database access error occurs or the specified - * columnLabel is not valid - */ - @Override - public void updateBlob(final String columnLabel, final InputStream inputStream) throws SQLException { - resultSet.updateBlob(columnLabel, inputStream); - } - - /** - * Updates the designated column with a Clob value. The data will be read from the provided Reader - * object for the specified number of characters. - * - * @param columnIndex the index of the column to update, starting from 1 - */ - @Override - public void updateClob(final int columnIndex, final Reader reader, final long length) throws SQLException { - resultSet.updateClob(columnIndex, reader, length); - } - - /** - * Updates the designated column with a character stream containing a CLOB value. - * The data in the stream will be read into the CLOB value, starting at the beginning. - * The length parameter indicates the number of characters to read from the reader. - * - * @param columnLabel the label for the column specified with the SQL AS clause - * or the column name - * @param reader the java.io.Reader object containing the data to set as the CLOB value - * @param length the length of the data to be written to the CLOB column in characters - * @throws SQLException if a database access error occurs, this method is called on a closed result set, - * if the designated column does not have a CLOB data type, - * or if the length specified is invalid - */ - @Override - public void updateClob(final String columnLabel, final Reader reader, final long length) throws SQLException { - resultSet.updateClob(columnLabel, reader, length); - } - - /** - * Updates the designated Clob column using the data provided by a Reader object. - * The new data will overwrite the existing Clob value at the specified column index. - * - * @param columnIndex the index of the column to be updated, starting from 1 - * @param reader the Reader object that contains the new Clob data to set - * @throws SQLException if a database access error occurs or the column index is invalid - */ - @Override - public void updateClob(final int columnIndex, final Reader reader) throws SQLException { - resultSet.updateClob(columnIndex, reader); - } - - /** - * Updates the designated Clob column with the given character stream reader. - * - * @param columnLabel the label for the column specified with a SQL identifier - * @param reader the Reader object that contains the new Clob data - * @throws SQLException if a database access error occurs or the columnLabel is not valid - */ - @Override - public void updateClob(final String columnLabel, final Reader reader) throws SQLException { - resultSet.updateClob(columnLabel, reader); - } - - /** - * Updates the designated column with a character stream value, which will have - * a specified number of characters, in the current row of this ResultSet object. - * - * @param columnIndex the column index (starting from 1) indicating the column to be updated - * @param reader the java.io.Reader object that contains the data to be written to the NClob column - * @param length the number of characters in the stream to be written to the column - * @throws SQLException if a database access error occurs, second parameter is null, or this method is - * called on a closed ResultSet - */ - @Override - public void updateNClob(final int columnIndex, final Reader reader, final long length) throws SQLException { - resultSet.updateNClob(columnIndex, reader, length); - } - - /** - * Updates the designated column with a new CLOB value. The data will be read from the supplied Reader - * and will have the specified length. The column is identified using its label. - * - * @param columnLabel the label for the column to be updated - * @param reader the Reader object that contains the data to update the CLOB value - * @param length the number of characters in the Reader to be read - * @throws SQLException if a database access error occurs or the columnLabel is not valid - */ - @Override - public void updateNClob(final String columnLabel, final Reader reader, final long length) throws SQLException { - resultSet.updateNClob(columnLabel, reader, length); - } - - /** - * Updates the designated NClob column with a Reader object. The data in the Reader object - * will be written to the NClob value that is being updated. This method is typically used - * when working with large NClob data. - * - * @param columnIndex the index of the column to update (1-based index) - * @param reader the java.io.Reader object containing the data to set the NClob value - * @throws SQLException if a database access error occurs or the method is called on - * a closed ResultSet - */ - @Override - public void updateNClob(final int columnIndex, final Reader reader) throws SQLException { - resultSet.updateNClob(columnIndex, reader); - } - - /** - * Updates the designated column with a new NClob value. The data is read - * from the provided Reader object. - * - * @param columnLabel the label for the column to be updated - * @param reader the java.io.Reader object from which the NClob value will be read - * @throws SQLException if a database access error occurs or the Reader object is null - */ - @Override - public void updateNClob(final String columnLabel, final Reader reader) throws SQLException { - resultSet.updateNClob(columnLabel, reader); - } - - /** - * Retrieves an object from the specified column index in the result set and converts it to the specified type. - * - * @param the type of the object to be retrieved - * @param columnIndex the index of the column from which the object is to be retrieved, starting at 1 - * @param type the Class object representing the type to which the object should be converted - * @return the object from the specified column converted to the specified type - * @throws SQLException if a database access error occurs or this method is called on a closed result set - */ - @Override - public T getObject(final int columnIndex, final Class type) throws SQLException { - return resultSet.getObject(columnIndex, type); - } - - /** - * Retrieves an object from the specified column label in the result set and casts it to the provided type. - * - * @param columnLabel the label for the column from which the object will be retrieved - * @param type the class of the object to be retrieved - * @return the object retrieved from the specified column, cast to the specified type - * @throws SQLException if a database access error occurs or the column label is not valid - */ - @Override - public T getObject(final String columnLabel, final Class type) throws SQLException { - return resultSet.getObject(columnLabel, type); - } - - /** - * Updates the designated column with an object value. The update will be applied to the column - * specified by the given column index. This method allows specifying a SQL target type and a scale - * or length for the object being updated. - * - * @param columnIndex the index of the column to update*/ - @Override - public void updateObject(final int columnIndex, final Object x, final SQLType targetSqlType, final int scaleOrLength) - throws SQLException { - resultSet.updateObject(columnIndex, x, targetSqlType, scaleOrLength); - } - - /** - * Updates the designated column with an object value. - * The object will be converted to the specified SQL type before being updated. - * - * @param columnLabel the label for the column to be updated - * @param x the object containing the value to be stored in the specified column - * @param targetSqlType the SQL type to convert the object to - * @param scaleOrLength for numeric data, this is the number of digits after the decimal point; - * for non-numeric data, this is the length of the data - * @throws SQLException if a database access error occurs, this method is called on a closed ResultSet, - * or the target SQL type is invalid - */ - @Override - public void updateObject(final String columnLabel, final Object x, final SQLType targetSqlType, final int scaleOrLength) - throws SQLException { - resultSet.updateObject(columnLabel, x, targetSqlType, scaleOrLength); - } - - /** - * Updates the designated column with an object value. The update is made to - * the current row of the ResultSet object. This method allows specifying - * the column index and the target SQL type for the object being updated. - * - * @param columnIndex the index of the column to update, starting from 1 - * @param x the object containing the new column value - * @param targetSqlType the SQL type to be sent to the database - * @throws SQLException if a database access error occurs or if the specified - * parameters are invalid - */ - @Override - public void updateObject(final int columnIndex, final Object x, final SQLType targetSqlType) throws SQLException { - resultSet.updateObject(columnIndex, x, targetSqlType); - } - - /** - * Updates the value of the designated column with the given column label in the current row of this - * ResultSet object to the provided Java object. The data will be converted to the SQL type specified - * by the given targetSqlType parameter before updating. - * - * @param columnLabel the label for the column to be updated - * @param x the new column value - * @param targetSqlType the SQL type to be used for data conversion before updating - * @throws SQLException if a database access error occurs or if the columnLabel is not valid - */ - @Override - public void updateObject(final String columnLabel, final Object x, final SQLType targetSqlType) throws SQLException { - resultSet.updateObject(columnLabel, x, targetSqlType); - } - - /** - * Updates the designated column with an ASCII InputStream. - * The stream must contain only ASCII characters. The driver reads the stream to the end. - * - * @param columnIndex the index of the column to update, starting from 1. - * @param x the InputStream containing ASCII data to set in the specified column. - * @throws SQLException if a database access error occurs or the columnIndex is invalid. - */ - @Override - public void updateAsciiStream(final int columnIndex, final InputStream x) throws SQLException { - resultSet.updateAsciiStream(columnIndex, x); - } - - /** - * Updates the designated column with a binary stream value. - * The data provided in the stream replaces the existing value of the column - * at the specified index in the current row of the ResultSet. - * - * @param columnIndex the index of the column to be updated, where the first column is 1 - * @param x the InputStream containing the binary data to set in the column - * @throws SQLException if a database access error occurs or the ResultSet is in a state - * that does not permit the update - */ - @Override - public void updateBinaryStream(final int columnIndex, final InputStream x) throws SQLException { - resultSet.updateBinaryStream(columnIndex, x); - } - - /** - * Updates the designated column with a new character stream value. - * The data will be read from the provided Reader object and written to the database. - * - * @param columnIndex the index of the column to be updated, starting from 1 - * @param x the Reader object containing the new character stream value - * @throws SQLException if a database access error occurs or the columnIndex is invalid - */ - @Override - public void updateCharacterStream(final int columnIndex, final Reader x) throws SQLException { - resultSet.updateCharacterStream(columnIndex, x); - } - - /** - * Updates the designated column with an ASCII stream. - * The data will be read from the input stream as needed until the end of the stream is reached. - * This method can be used to update columns in the current row or the insert row. - * - * @param columnLabel the label for the column specified with the SQL AS clause. - * If the SQL AS clause was not specified, the label will default to the column name. - * @param x the InputStream object containing the ASCII stream data to set in the column - * @throws SQLException if a database access error occurs, this method is called on a closed result set, - * or if the ResultSet concurrency is CONCUR_READ_ONLY - */ - @Override - public void updateAsciiStream(final String columnLabel, final InputStream x) throws SQLException { - resultSet.updateAsciiStream(columnLabel, x); - } - - /** - * Updates the designated column with a binary stream value. The column is specified by the column label. - * The data in the InputStream can be used as an updated value for the column. - * - * @param columnLabel the label for the column to be updated. - * @param x the InputStream containing the binary stream data to update the column with. - * @throws SQLException if a database access error occurs or the column label is not valid. - */ - @Override - public void updateBinaryStream(final String columnLabel, final InputStream x) throws SQLException { - resultSet.updateBinaryStream(columnLabel, x); - } - - /** - * Updates the designated column with a new character stream value. - * The data will be read from the provided Reader object and sent to the database. - * - * @param columnLabel the label for the column that is to be updated - * @param reader the Reader object containing the data to set the specified column to - * @throws SQLException if a database access error occurs, this method is called on a closed result set, - * or the columnLabel is invalid - */ - @Override - public void updateCharacterStream(final String columnLabel, final Reader reader) throws SQLException { - resultSet.updateCharacterStream(columnLabel, reader); - } - - /** - * Retrieves the value of the designated column in the current row of this ResultSet object - * as a java.net.URL object. - * - * @param columnIndex the index of the column from which the URL is to be retrieved, where*/ - @Override - public URL getURL(final int columnIndex) throws SQLException { - return resultSet.getURL(columnIndex); - } - - /** - * Retrieves the value of the designated column as a URL object. - * - * @param columnLabel the label for the column, which is the column name defined during table creation - * @return the column value as a URL object, or null if the SQL value is SQL NULL - * @throws SQLException if a database access error occurs or the columnLabel is not valid - */ - @Override - public URL getURL(final String columnLabel) throws SQLException { - return resultSet.getURL(columnLabel); - } - - /** - * Updates the designated column with a Ref value. - * The updater methods are used to update column values in the current row - * or the insert row. The new row value will be updated into the database - * when the method updateRow is called. - * - * @param columnIndex the first column is 1, the second is 2, and so on - * @param x the new column value; must be a Ref object - * @throws SQLException if a database access error occurs, if the result set - * concurrency is CONCUR_READ_ONLY, or if this method - * is called on a closed result set - */ - @Override - public void updateRef(final int columnIndex, final Ref x) throws SQLException { - resultSet.updateRef(columnIndex, x); - } - - /** - * Updates the designated column with a Ref value. - * This method should be called when updating a column in a ResultSet with a Ref object. - * - * @param columnLabel the label for the column specified in the query, used to identify the column being updated - * @param x the Ref object containing the value to update the column with - * @throws SQLException if a database access error occurs, the ResultSet is in a read-only mode, - * or if this method is called on a non-updatable ResultSet - */ - @Override - public void updateRef(final String columnLabel, final Ref x) throws SQLException { - resultSet.updateRef(columnLabel, x); - } - - /** - * Checks if this object wraps an implementation of the specified interface. - * - * @param iface the interface to check if the object implements or wraps. - * @return true if this object is a wrapper for the specified interface; false otherwise. - * @throws SQLException if a database access error occurs. - */ - @Override - public boolean isWrapperFor(final Class iface) throws SQLException { - return resultSet.isWrapperFor(iface); - } - - /** - * Unwraps this instance to provide an implementation of the specified interface. - * - * @param the type of the class modeled by the specified interface - * @param iface the class of the interface to be unwrapped - * @return an instance of the specified interface, which this object implements - * @throws SQLException if no object implements the specified interface or if an error occurs - */ - @Override - public T unwrap(final Class iface) throws SQLException { - return resultSet.unwrap(iface); - } + /** + * Represents the result set obtained from executing a database query. + * This object provides functionality to traverse and access the data + * in a tabular format returned by the query execution. + *

+ * This ResultSet instance is immutable and cannot be modified after initialization. + * It is typically used for reading query results and is tied to a specific + * SQL query execution lifecycle. + */ + private final ResultSet resultSet; + + /** + * Initializes a new instance of the TrimmingResultSet class, wrapping the provided ResultSet. + * + * @param resultSet the ResultSet to be wrapped and processed by this TrimmingResultSet instance + */ + public TrimmingResultSet(ResultSet resultSet) { + this.resultSet = resultSet; + } + + /** + * Moves the cursor forward one row from its current position in the ResultSet. + * + * @return true if the new current row is valid, false if there are no more rows + * @throws SQLException if a database access error occurs or this method is called on a closed ResultSet + */ + @Override + public boolean next() throws SQLException { + return resultSet.next(); + } + + /** + * Closes the current resource associated with this instance. + * This method ensures that the ResultSet object is properly closed to + * release database and JDBC resources. + * + * @throws SQLException if a database access error occurs while closing the ResultSet. + */ + @Override + public void close() throws SQLException { + resultSet.close(); + } + + /** + * Checks if the last column read had a value of SQL NULL. + * This method should be called only after calling a getter method + * on the ResultSet to retrieve a column value. + * + * @return true if the last column read was SQL NULL; false otherwise + * @throws SQLException if a database access error occurs + */ + @Override + public boolean wasNull() throws SQLException { + return resultSet.wasNull(); + } + + /** + * Retrieves the string value from the specified column index of the current row in the ResultSet. + * The value is trimmed to remove leading and trailing whitespace. If the value is null, it returns null. + * + * @param columnIndex the column index, starting from 1, from which the string is to be retrieved + * @return the trimmed string value from the specified column, or null if the column value is SQL NULL + * @throws SQLException if a database access error occurs or the columnIndex is not valid + */ + @Override + public String getString(final int columnIndex) throws SQLException { + String value = resultSet.getString(columnIndex); + return value != null ? value.trim() : null; + } + + /** + * Retrieves the value of the designated column in the current row of the result set + * as a boolean. + * + * @param columnIndex the index of the column, starting from 1 + * @return the column value as a boolean + * @throws SQLException if a database access error occurs or the columnIndex is out of bounds + */ + @Override + public boolean getBoolean(final int columnIndex) throws SQLException { + return resultSet.getBoolean(columnIndex); + } + + /** + * Retrieves the value of the designated column in the current row + * of this ResultSet object as a byte. + * + * @param columnIndex the first column is 1, the second is 2, and so on; + * must be a valid column index + * @return the column value as a byte + * @throws SQLException if the column index is invalid or if a database access error occurs + */ + @Override + public byte getByte(final int columnIndex) throws SQLException { + return resultSet.getByte(columnIndex); + } + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object + * as a short. + * + * @param columnIndex the column index, starting from 1, which indicates the column to retrieve + * the short value from + * @return the column value as a short + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public short getShort(final int columnIndex) throws SQLException { + return resultSet.getShort(columnIndex); + } + + /** + * Retrieves the value of the column specified by the given index as an int. + * + * @param columnIndex the index of the column in the current row, starting from 1 + * @return the column value as an int + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public int getInt(final int columnIndex) throws SQLException { + return resultSet.getInt(columnIndex); + } + + /** + * Retrieves the value of the designated column in the current row of the ResultSet + * as a long value. + * + * @param columnIndex the index of the column from which to retrieve the value, starting from 1 + * @return the long value of the designated column + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public long getLong(final int columnIndex) throws SQLException { + return resultSet.getLong(columnIndex); + } + + /** + * Retrieves the value of the designated column in the current row of this + * ResultSet as a float. + * + * @param columnIndex the index of the column, starting from 1, from which + * the float value is to be retrieved + * @return the column value as a float + * @throws SQLException if a database access error occurs or the column + * index is invalid + */ + @Override + public float getFloat(final int columnIndex) throws SQLException { + return resultSet.getFloat(columnIndex); + } + + /** + * Retrieves the value of the designated column in the current row of this + * ResultSet object as a double. + * + * @param columnIndex the index of the column, starting from 1, from which + * the double value is to be retrieved + * @return the column value as a double + * @throws SQLException if a database access error occurs or the column + * index is invalid + */ + @Override + public double getDouble(final int columnIndex) throws SQLException { + return resultSet.getDouble(columnIndex); + } + + /** + * Retrieves the value of the specified column as a BigDecimal object with the specified scale. + * + * @param columnIndex the index of the column (1-based) from which to retrieve the BigDecimal value + * @param scale the scale to apply to the retrieved BigDecimal value + * @return the BigDecimal value from the specified column with the given scale + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + @Deprecated + public BigDecimal getBigDecimal(final int columnIndex, int scale) throws SQLException { + return resultSet.getBigDecimal(columnIndex, scale); + } + + /** + * Retrieves the value of the designated column in the current row of this ResultSet + * object as a byte array. + * + * @param columnIndex the first column is 1, the second is 2, and so on; indicates + * which column value to retrieve. + * @return the column value as a byte array. Returns null if the SQL value is + * SQL NULL. + * @throws SQLException if the columnIndex is invalid or a database access error occurs. + */ + @Override + public byte[] getBytes(final int columnIndex) throws SQLException { + return resultSet.getBytes(columnIndex); + } + + /** + * Retrieves the value of the designated column in the current row of this result set + * as a {@code Date} object. + * + * @param columnIndex the first column is 1, the second column is 2, and so on + * @return the {@code Date} value of the specified column in the current row + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public Date getDate(final int columnIndex) throws SQLException { + return resultSet.getDate(columnIndex); + } + + /** + * Retrieves the value of the designated column as a {@code Time} object. + * + * @param columnIndex the index of the column, starting from 1 + * @return the {@code Time} value of the specified column in the current row + * @throws SQLException if the column index is invalid or a database access error occurs + */ + @Override + public Time getTime(final int columnIndex) throws SQLException { + return resultSet.getTime(columnIndex); + } + + /** + * Retrieves the value of the designated column in the current row of this + * ResultSet object as a Timestamp object. + * + * @param columnIndex the column index, starting at 1, from which the timestamp + * value is to be retrieved + * @return a Timestamp object representing the SQL TIMESTAMP value in the specified + * column of the current row + * @throws SQLException if a database access error occurs, the column index is invalid, + * or the data in the column is not a valid timestamp + */ + @Override + public Timestamp getTimestamp(final int columnIndex) throws SQLException { + return resultSet.getTimestamp(columnIndex); + } + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of ASCII characters. + * + * @param columnIndex the column index, starting from 1, indicating which column's value to retrieve + * @return an InputStream object that contains the ASCII data of the specified column + * @throws SQLException if a database access error occurs or the columnIndex is invalid + */ + @Override + public InputStream getAsciiStream(final int columnIndex) throws SQLException { + return resultSet.getAsciiStream(columnIndex); + } + + /** + * Retrieves the value of the designated column in the current row as a stream of Unicode characters. + * The stream is read in the Java Unicode character format. + * This method is used to access database data as Unicode text. + * + * @param columnIndex the index of the column in the result set, starting from 1 for the first column + * @return an InputStream object that provides a stream of Unicode characters, + * or null if the SQL value is null + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public InputStream getUnicodeStream(final int columnIndex) throws SQLException { + return null; + } + + /** + * Retrieves the value of the designated + */ + @Override + public InputStream getBinaryStream(final int columnIndex) throws SQLException { + return resultSet.getBinaryStream(columnIndex); + } + + /** + * Retrieves the value of the specified column as a trimmed string. + * + * @param columnLabel the label of the column from which to retrieve the value + * @return the trimmed string value of the specified column, or null if the column value is SQL NULL + * @throws SQLException if a database access error occurs or the columnLabel is invalid + */ + @Override + public String getString(final String columnLabel) throws SQLException { + String value = resultSet.getString(columnLabel); + return value != null ? value.trim() : null; + } + + /** + * Retrieves the value of the designated column as a boolean. + * + * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, + * then the label is the name of the column. + * @return the column value as a boolean. Returns false if the value in the designated column is SQL NULL. + * @throws SQLException if a database access error occurs or the column label is not valid. + */ + @Override + public boolean getBoolean(final String columnLabel) throws SQLException { + return resultSet.getBoolean(columnLabel); + } + + /** + * Retrieves the value of the designated column in the current row of this ResultSet + * object as a byte. + * + * @param columnLabel the label for the column specified with the SQL AS clause. + * If the SQL AS clause was not specified, then the label is + * the name of the column. + * @return the column value as a byte. If the value is SQL NULL, the result is 0. + * @throws SQLException if the columnLabel is not valid or a database access error occurs. + */ + @Override + public byte getByte(final String columnLabel) throws SQLException { + return resultSet.getByte(columnLabel); + } + + /** + * Retrieves the value of the specified column as a short. + * + * @param columnLabel the label for the column specified with the SQL query + * @return the column value as a short + * @throws SQLException if a database access error occurs or the columnLabel is not valid + */ + @Override + public short getShort(final String columnLabel) throws SQLException { + return resultSet.getShort(columnLabel); + } + + /** + * Retrieves the value of the column designated by the given label as an int. + * + * @param columnLabel the label for the column specified with the SQL AS clause, or the original column name + * @return the column value as an int + * @throws SQLException if a database access error occurs or the column label is not valid + */ + @Override + public int getInt(final String columnLabel) throws SQLException { + return resultSet.getInt(columnLabel); + } + + /** + * Retrieves the value of the specified column as a long. + * + * @param columnLabel the name of the column from which to retrieve the value + * @return the long value of the specified column + * @throws SQLException if a database access error occurs or the column label is not valid + */ + @Override + public long getLong(final String columnLabel) throws SQLException { + return resultSet.getLong(columnLabel); + } + + /** + * Retrieves the value of the specified column as a float from the result set. + * + * @param columnLabel the label for the column specified in the SQL query + * @return the column value as a float + * @throws SQLException if a database access error occurs or the columnLabel is not valid + */ + @Override + public float getFloat(final String columnLabel) throws SQLException { + return resultSet.getFloat(columnLabel); + } + + /** + * Retrieves the value of the designated column as a double. + * + * @param columnLabel the label for the column specified in the SQL query + * @return the column value as a double + * @throws SQLException if a database access error occurs or the columnLabel is not valid + */ + @Override + public double getDouble(final String columnLabel) throws SQLException { + return resultSet.getDouble(columnLabel); + } + + /** + * Retrieves the value of the designated column as a {@code BigDecimal} with the specified scale. + * + * @param columnLabel the label for the column in the SQL result set + * @param scale the number of digits to the right of the decimal point + * @return the value of the column as a {@code BigDecimal} with the specified scale + * @throws SQLException if a database access error occurs or this method is called on a closed result set + */ + @Override + @Deprecated + public BigDecimal getBigDecimal(final String columnLabel, int scale) throws SQLException { + return resultSet.getBigDecimal(columnLabel, scale); + } + + /** + * Retrieves the value of the specified column in the current row of this ResultSet + * as a byte array. The column is specified using the column label. + * + * @param columnLabel the label for the column from which to retrieve the value + * @return a byte array containing the column value; null if the value is SQL NULL + * @throws SQLException if a database access error occurs or the column label is invalid + */ + @Override + public byte[] getBytes(final String columnLabel) throws SQLException { + return resultSet.getBytes(columnLabel); + } /** + * Retrieves the value of the designated column as a Date object + * using the given Calendar object for interpreting the timezone. + * + * @param columnIndex the index of the column, starting from 1 + * @param cal the Calendar object to use for interpreting dates, or null + * @return the value of the column as a Date object; + * if the value is SQL NULL, the result is null + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public Date getDate(final int columnIndex, final Calendar cal) throws SQLException { + return resultSet.getDate(columnIndex, cal); + } + + /** + * Retrieves the date value of the specified column. + * + * @param columnLabel the label of the column from which the date value is to be retrieved + * @return the date value of the specified column, or null if the value is SQL NULL + * @throws SQLException if a database access error occurs or the column label is invalid + */ + @Override + public Date getDate(final String columnLabel) throws SQLException { + return resultSet.getDate(columnLabel); + } + + /** + * Retrieves the value of the specified column as a {@code Time} object. + * + * @param columnLabel the label of the column from which to retrieve the value + * @return a {@code Time} object representing the value of the specified column + * @throws SQLException if a database access error occurs or the columnLabel is not valid + */ + @Override + public Time getTime(final String columnLabel) throws SQLException { + return resultSet.getTime(columnLabel); + } /** + * Retrieves the value of the specified column as a Date object using the given Calendar instance to construct the date. + * + * @param columnLabel the label for the column from which to retrieve the value + * @param cal the Calendar instance to use for determining the date + * @return the column value as a Date object; if the value is SQL NULL, the result is null + * @throws SQLException if a database access error occurs or the column label is invalid + */ + @Override + public Date getDate(final String columnLabel, final Calendar cal) throws SQLException { + return resultSet.getDate(columnLabel, cal); + } + + /** + * Retrieves the timestamp value for the specified column label from the underlying result set. + * + * @param columnLabel the label for the column from which to retrieve the timestamp + * @return the timestamp value of the specified column; may return null if the value is SQL NULL + * @throws SQLException if a database access error occurs or if the column label is invalid + */ + @Override + public Timestamp getTimestamp(final String columnLabel) throws SQLException { + return resultSet.getTimestamp(columnLabel); + } + + /** + * Retrieves the value of the specified column as a stream of ASCII characters. + * + * @param columnLabel the label for the column from which the stream will be retrieved + * @return an InputStream object containing the ASCII stream of the designated column value + * @throws SQLException if a database access error occurs or the columnLabel is not valid + */ + @Override + public InputStream getAsciiStream(final String columnLabel) throws SQLException { + return resultSet.getAsciiStream(columnLabel); + } + + /** + * Retrieves the value of the designated column labeled by the given column label + * as a Unicode stream. The data will be returned as a stream of Unicode characters. + * This method is intended for reading long text values or other binary data + * that can be represented as Unicode. + * + * @param columnLabel the label for the column specified in the SQL query + * @return an InputStream containing the Unicode stream of the designated column, + * or null if the value is SQL NULL + * @throws SQLException if a database access error occurs or if the columnLabel + * does not match an existing column + */ + @Override + public InputStream getUnicodeStream(final String columnLabel) throws SQLException { + return null; + } + + /** + * Retrieves the value of the designated column as a binary input stream. + * + * @param columnLabel the label for the column specified in the SQL query + * @return an InputStream object that contains the binary data of the designated column + * @throws SQLException if the columnLabel is not valid; + * if a database access error occurs; + * or if this method is called on a closed result set + */ + @Override + public InputStream getBinaryStream(final String columnLabel) throws SQLException { + return resultSet.getBinaryStream(columnLabel); + } /** + * Retrieves the value of the designated column as a {@code Time} object. + * + * @param columnIndex an integer indicating the column index, starting at 1 + * @param cal the {@code Calendar} object to use for constructing the {@code Time} object + * @return the column value as a {@code Time} object or null if the column value is SQL {@code NULL} + * @throws SQLException if a database access error occurs, the column index is invalid, + * or the {@code Calendar} object is null + */ + @Override + public Time getTime(final int columnIndex, final Calendar cal) throws SQLException { + return resultSet.getTime(columnIndex, cal); + } + + /** + * Retrieves the first warning reported by calls on the underlying object. + * Subsequent warnings on the object are chained to the first SQLWarning object. + * + * @return the first SQLWarning object or null if there are no warnings + * @throws SQLException if a database access error occurs + */ + @Override + public SQLWarning getWarnings() throws SQLException { + return null; + } + + /** + * Clears all warnings reported on this ResultSet object. + *

+ * This method delegates the call to the underlying ResultSet's clearWarnings method, + * ensuring that any chain of warnings previously recorded is cleared. + * + * @throws SQLException if a database access error occurs or this method + * is called on a closed ResultSet. + */ + @Override + public void clearWarnings() throws SQLException { + resultSet.clearWarnings(); + } /** + * Retrieves the value of the specified column as a {@link Time} object using the given calendar for timezone adjustments. + * + * @param columnLabel the label for the column specified with the SQL query + * @param cal the {@link Calendar} object to use in constructing the date + * @return the column value as a {@link Time} object; if the value is SQL {@code NULL}, the result is {@code null} + * @throws SQLException if a database access error occurs or the column label is not valid + */ + @Override + public Time getTime(final String columnLabel, final Calendar cal) throws SQLException { + return resultSet.getTime(columnLabel, cal); + } + + /** + * Retrieves the name of the SQL cursor used by this ResultSet object, if available. + * + * @return the name of the SQL cursor, or null if the cursor does not have a name. + * @throws SQLException if a database access error occurs or this method is called on a closed result set. + */ + @Override + public String getCursorName() throws SQLException { + return resultSet.getCursorName(); + } + + /** + * Retrieves the metadata for the result set. + * + * @return a ResultSetMetaData object that contains information about the columns of the result set. + * @throws SQLException if a database access error occurs. + */ + @Override + public ResultSetMetaData getMetaData() throws SQLException { + return resultSet.getMetaData(); + } + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object + * as an Object. The type of the object returned is determined by the SQL type of the column. + * + * @param columnIndex the index of the column to retrieve, where the first column is 1 + * @return the value of the designated column as an Object; returns null if the value is SQL NULL + * @throws SQLException if a database access error occurs or the column index is out of bounds + */ + @Override + public Object getObject(final int columnIndex) throws SQLException { + return resultSet.getObject(columnIndex); + } + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object + * as an Object. + * + * @param columnLabel the label for the column specified with the SQL AS clause. + * If the SQL AS clause was not specified, the label is the name of the column. + * @return the value of the specified column as an Object + * @throws SQLException if a database access error occurs or this method is called on a closed ResultSet + */ + @Override + public Object getObject(final String columnLabel) throws SQLException { + return resultSet.getObject(columnLabel); + } /** + * Retrieves the value of the specified column as a {@code Timestamp} object, + * using the provided {@code Calendar} to construct the {@code Timestamp}. + * + * @param columnIndex the index of the column (1-based) whose value is to be retrieved + * @param cal the {@code Calendar} object to use for interpreting the timestamp + * @return the column value as a {@code Timestamp} object; returns {@code null} if the column value is SQL {@code NULL} + * @throws SQLException if the column index is invalid or a database access error occurs + */ + @Override + public Timestamp getTimestamp(final int columnIndex, final Calendar cal) throws SQLException { + return resultSet.getTimestamp(columnIndex, cal); + } + + /** + * Retrieves the column index for the specified column label in the result set. + * + * @param columnLabel the label of the column for which the index is to be retrieved + * @return the column index corresponding to the specified label + * @throws SQLException if the column label is not valid or a database access error occurs + */ + @Override + public int findColumn(final String columnLabel) throws SQLException { + return resultSet.findColumn(columnLabel); + } + + /** + * Retrieves the value of the designated column in the current row of + * this ResultSet object as a java.io.Reader object. + * + * @param columnIndex the column index (1-based) for which the character stream is to be retrieved + * @return a Reader object that contains the data of the specified column; if the value is SQL NULL, this method returns null + * @throws SQLException if a database access error occurs or this method is called on a closed result set + */ + @Override + public Reader getCharacterStream(final int columnIndex) throws SQLException { + return resultSet.getCharacterStream(columnIndex); + } /** + * Retrieves the value of the designated column as a {@code Timestamp} object in the specified calendar. + * This method uses the provided {@code Calendar} to construct the {@code Timestamp} object. + * + * @param columnLabel the label for the column from which to retrieve the value + * @param cal the {@code Calendar} object to use to construct the timestamp + * @return the column value as a {@code Timestamp}; if the value is SQL {@code NULL}, the value returned is {@code null} + * @throws SQLException if a database access error occurs or the column label is invalid + */ + @Override + public Timestamp getTimestamp(final String columnLabel, final Calendar cal) throws SQLException { + return resultSet.getTimestamp(columnLabel, cal); + } + + /** + * Retrieves the character stream for the value of the specified column label in the current row of this ResultSet. + * This allows reading character data from the column as a Reader. + * + * @param columnLabel the label for the column specified in the ResultSet object, which is typically the SQL AS name if available, or the actual column name. + * @return a Reader object containing the column value as a stream of characters; null if the value is SQL NULL. + * @throws SQLException if a database access error occurs or the columnLabel is not valid. + */ + @Override + public Reader getCharacterStream(final String columnLabel) throws SQLException { + return resultSet.getCharacterStream(columnLabel); + } + + /** + * Retrieves the value of the specified column as a {@code BigDecimal} object. + * + * @param columnIndex the column index (starting at 1) from which the BigDecimal value is to be retrieved + * @return the column value as a {@code BigDecimal}, or null if the column value is SQL NULL + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public BigDecimal getBigDecimal(final int columnIndex) throws SQLException { + return resultSet.getBigDecimal(columnIndex); + } + + /** + * Retrieves the value of the specified column as a {@code BigDecimal} object. + * + * @param columnLabel the label of the column from which to retrieve the value + * @return the column value as a {@code BigDecimal} object, or {@code null} if the value is SQL {@code NULL} + * @throws SQLException if an SQL error occurs while retrieving the value + */ + @Override + public BigDecimal getBigDecimal(final String columnLabel) throws SQLException { + return resultSet.getBigDecimal(columnLabel); + } + + /** + * Checks if the cursor is positioned before the first row in the result set. + * + * @return true if the cursor is before the first row; false otherwise + * @throws SQLException if a database access error occurs or this method is called on a closed result set + */ + @Override + public boolean isBeforeFirst() throws SQLException { + return resultSet.isBeforeFirst(); + } + + /** + * Checks if the cursor is positioned after the last row in the ResultSet. + * + * @return true if the cursor is after the last row; false otherwise. + * @throws SQLException if a database access error occurs or this method is called on a closed ResultSet. + */ + @Override + public boolean isAfterLast() throws SQLException { + return resultSet.isAfterLast(); + } + + /** + * Checks if the cursor is positioned on the first row of the ResultSet. + * + * @return true if the cursor is on the first row; false otherwise + * @throws SQLException if a database access error occurs or the result set is closed + */ + @Override + public boolean isFirst() throws SQLException { + return resultSet.isFirst(); + } + + /** + * Checks if the current row of the ResultSet object is the last row. + * + * @return true if the current row is the last row; false otherwise + * @throws SQLException if a database access error occurs or this method is called on a closed ResultSet + */ + @Override + public boolean isLast() throws SQLException { + return resultSet.isLast(); + } + + /** + * Moves the cursor of the underlying ResultSet to the position + * before the first row. This is typically used to start iterating + * through the rows of the ResultSet from the beginning. + * + * @throws SQLException if a database access error occurs, + * this method is called on a closed ResultSet, + * or the ResultSet type does not support this operation. + */ + @Override + public void beforeFirst() throws SQLException { + resultSet.beforeFirst(); + } + + /** + * Moves the cursor to the end of the ResultSet, just after the last row. + * This method is typically used to iterate backward through the ResultSet. + * + * @throws SQLException if a database access error occurs or the ResultSet + * is closed. + */ + @Override + public void afterLast() throws SQLException { + resultSet.afterLast(); + } + + /** + * Moves the cursor to the first row of this ResultSet object. + * + * @return true if the cursor is on a valid row; false if there are no rows in the ResultSet. + * @throws SQLException if a database access error occurs or this method is called on a closed ResultSet. + */ + @Override + public boolean first() throws SQLException { + return resultSet.first(); + } + + /** + * Moves the cursor to the last row in the result set. + * + * @return true if the cursor is moved to a valid row; false if there are no rows in the result set. + * @throws SQLException if a database access error occurs or the result set type does not support this operation. + */ + @Override + public boolean last() throws SQLException { + return resultSet.last(); + } /** + * Retrieves the NString value at the specified column index from the underlying result set. + * If the value is not null, it trims any leading or trailing whitespace characters. + * + * @param columnIndex the index of the column from which to retrieve the NString value, starting from 1 + * @return the trimmed NString value at the specified column index, or null if the value is null + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public String getNString(final int columnIndex) throws SQLException { + String value = resultSet.getNString(columnIndex); + return value != null ? value.trim() : null; + } + + /** + * Retrieves the current row number from the underlying ResultSet object. + * + * @return the current row number, or 0 if there is no current row + * @throws SQLException if a database access error occurs or this method is called on a closed result set + */ + @Override + public int getRow() throws SQLException { + return resultSet.getRow(); + } + + /** + * Moves the cursor to the given row number in this result set. + * + * @param row the row number to move the cursor to. A positive number moves the cursor + * to the given row number with respect to the beginning, while a negative + * number moves the cursor with respect to the end. + * @return true if the cursor is on a valid row after the move; false if the cursor + * is positioned before the first row or after the last row. + * @throws SQLException if a database access error occurs or the result set is closed. + */ + @Override + public boolean absolute(final int row) throws SQLException { + return resultSet.absolute(row); + } /** + * Retrieves the value of the designated column as a string in the current row of the result set. + * The string is processed to ensure leading and trailing whitespace is removed. + * + * @param columnLabel the label for the column specified in the query + * @return the column value as a trimmed string, or null if the value is SQL NULL + * @throws SQLException if the columnLabel is not valid, if there is a database access error, or other SQL issues occur + */ + @Override + public String getNString(final String columnLabel) throws SQLException { + String value = resultSet.getNString(columnLabel); + return value != null ? value.trim() : null; + } + + /** + * Moves the cursor a relative number of rows, either forward or backward, from its current position. + * Positive values move the cursor forward, and negative values move it backward. + * + * @param rows the number of rows to move the cursor relative to its current position + * @return {@code true} if the cursor is on a valid row after the move; {@code false} if the cursor is positioned before the first row or after the last row + * @throws SQLException if a database access error occurs or the result set is closed + */ + @Override + public boolean relative(final int rows) throws SQLException { + return resultSet.relative(rows); + } + + /** + * Moves the cursor to the previous row in the result set. + * + * @return true if the cursor is moved to a valid row; false if there are no more rows. + * @throws SQLException if a database access error occurs or the result set is closed. + */ + @Override + public boolean previous() throws SQLException { + return resultSet.previous(); + } /** + * Retrieves the value of the designated column in the current row of + * this ResultSet object as a Reader object. The column value is expected + * to be a national character stream in the Java programming language. + * + * @param columnIndex the column index (1-based) of the desired column in this ResultSet + * @return a Reader object that contains the column value; if the value is SQL NULL, then null is returned + * @throws SQLException if the columnIndex is invalid or a database access error occurs + */ + @Override + public Reader getNCharacterStream(final int columnIndex) throws SQLException { + return resultSet.getNCharacterStream(columnIndex); + } + + /** + * Unwraps this instance to provide an implementation of the specified interface. + * + * @param the type of the class modeled by the specified interface + * @param iface the class of the interface to be unwrapped + * @return an instance of the specified interface, which this object implements + * @throws SQLException if no object implements the specified interface or if an error occurs + */ + @Override + public T unwrap(final Class iface) throws SQLException { + return resultSet.unwrap(iface); + } + + /** + * Checks if this object wraps an implementation of the specified interface. + * + * @param iface the interface to check if the object implements or wraps. + * @return true if this object is a wrapper for the specified interface; false otherwise. + * @throws SQLException if a database access error occurs. + */ + @Override + public boolean isWrapperFor(final Class iface) throws SQLException { + return resultSet.isWrapperFor(iface); + } /** + * Retrieves the value of the designated column in the current row of this ResultSet + * object as a character stream in the form of a Reader. + * + * @param columnLabel the label for the column specified in the SQL query + * @return a Reader object that contains the column value; if the column value is SQL NULL, the value returned is null + * @throws SQLException if the columnLabel is not valid, the result set is closed, or a database access error occurs + */ + @Override + public Reader getNCharacterStream(final String columnLabel) throws SQLException { + return resultSet.getNCharacterStream(columnLabel); + } + + + + + + + + + + + + + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object + * as an Object in the Java programming language. The value will be converted to the specified + * Java class using the provided type map. + * + * @param columnIndex the first column is 1, the second is 2, and so on; must be in the range + * [1, number of columns in the current row]. + * @param map a mapping of SQL structured types or SQL DISTINCT types to classes in the Java + * programming language. The type map parameter overrides the default type map + * associated with the connection for this call only. + * @return an Object that represents the SQL value in the specified column, converted to a + * Java object using the provided type map. Returns null if the SQL value is SQL NULL. + * @throws SQLException if a database access error occurs, the columnIndex is out of bounds, + * or if the type map is invalid. + */ + @Override + public Object getObject(final int columnIndex, final Map> map) throws SQLException { + return resultSet.getObject(columnIndex, map); + } + + + + /** + * Retrieves the value of the specified column as a {@link Ref} object. + * + * @param columnIndex the 1-based index of the column from which the value is to be retrieved + * @return the value of the specified column as a {@link Ref} object, or null if the value is SQL NULL + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public Ref getRef(final int columnIndex) throws SQLException { + return resultSet.getRef(columnIndex); + } + + + + /** + * Retrieves the Blob object designated by the given column index from the current row of the result set. + * + * @param columnIndex the column index, starting from 1, from which the Blob object is to be retrieved. + * @return the Blob object at the specified column index; may be null if the SQL value is SQL NULL. + * @throws SQLException if a database access error occurs or if this method is called on a closed result set. + */ + @Override + public Blob getBlob(final int columnIndex) throws SQLException { + return resultSet.getBlob(columnIndex); + } + + + + /** + * Retrieves the CLOB value at the specified column index from the underlying ResultSet. + * + * @param columnIndex the 1-based index of the column from which the CLOB is to be retrieved + * @return the CLOB value from the specified column, or null if the column value is SQL NULL + * @throws SQLException if a database access error occurs or the columnIndex is invalid + */ + @Override + public Clob getClob(final int columnIndex) throws SQLException { + return resultSet.getClob(columnIndex); + } + + + + /** + * Retrieves an SQL Array object from the specified column index + * of the current row in the ResultSet. + * + * @param columnIndex the index of the column to retrieve the Array from, starting from 1 + * @return an Array object representing the SQL Array value at the specified column index + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public Array getArray(final int columnIndex) throws SQLException { + return resultSet.getArray(columnIndex); + } + + /** + * Retrieves the value of the specified column as an Object, using the given type map for + * custom mappings of SQL user-defined types to Java classes. + * + * @param columnLabel the label for the column from which to retrieve the value + * @param map a map of SQL type names to Java classes for custom type mappings + * @return the value of the specified column as an Object, or null if the value is SQL NULL + * @throws SQLException if a database access error occurs, the columnLabel is not valid, + * or a mapping for a user-defined type is invalid + */ + @Override + public Object getObject(final String columnLabel, final Map> map) throws SQLException { + return resultSet.getObject(columnLabel, map); + } + + /** + * Retrieves the value of the designated column as a Ref object. + * + * @param columnLabel the label for the column specified with the SQL AS clause. + * If the SQL AS clause was not specified, then the label is the name of the column. + * @return a Ref object representing the SQL REF value in the specified column. + * @throws SQLException if a database access error occurs or this method + * is called on a closed result set. + */ + @Override + public Ref getRef(final String columnLabel) throws SQLException { + return resultSet.getRef(columnLabel); + } + + /** + * Retrieves the value of the designated column as a {@code Blob} object. + * + * @param columnLabel the label for the column specified, which is the name of the column as defined in the database + * @return the {@code Blob} object representing the value of the specified column + * @throws SQLException if a database access error occurs or the column label is not valid + */ + @Override + public Blob getBlob(final String columnLabel) throws SQLException { + return resultSet.getBlob(columnLabel); + } + + /** + * Retrieves the CLOB (Character Large Object) value of the designated column + * as specified by the column label. + * + * @param columnLabel the label for the column from which to retrieve the CLOB value + * @return the CLOB object containing the value of the designated column + * @throws SQLException if a database access error occurs or the columnLabel is invalid + */ + @Override + public Clob getClob(final String columnLabel) throws SQLException { + return resultSet.getClob(columnLabel); + } + + /** + * Retrieves the SQL {@code Array} object designated by the specified column label. + * + * @param columnLabel the label for the column from which to retrieve the SQL {@code Array} + * @return the SQL {@code Array} object for the specified column label, or {@code null} if the SQL value is {@code NULL} + * @throws SQLException if the column label is not valid or a database access error occurs + */ + @Override + public Array getArray(final String columnLabel) throws SQLException { + return resultSet.getArray(columnLabel); + } + + /** + * Retrieves the current fetch direction for the underlying ResultSet. + * + * @return the current fetch direction; this will be one of ResultSet.FETCH_FORWARD, + * ResultSet.FETCH_REVERSE, or ResultSet.FETCH_UNKNOWN. + * @throws SQLException if a database access error occurs or if the ResultSet is closed. + */ + @Override + public int getFetchDirection() throws SQLException { + return resultSet.getFetchDirection(); + } + + /** + * Sets the fetch direction for the ResultSet object to the given direction value. + * The fetch direction gives a hint to the driver about the direction in which + * the rows in the ResultSet will be processed. + * + * @param direction an integer value indicating the fetch direction. + * The allowed values are ResultSet.FETCH_FORWARD, + * ResultSet.FETCH_REVERSE, or ResultSet.FETCH_UNKNOWN. + * @throws SQLException if a database access error occurs or the given + * fetch direction is not supported. + */ + @Override + public void setFetchDirection(final int direction) throws SQLException { + resultSet.setFetchDirection(direction); + } + + /** + * Retrieves the fetch size for the ResultSet associated with this method. + * The fetch size determines how many rows the database fetches at a time from + * the database server when more rows are needed for processing. + * + * @return the fetch size for the ResultSet + * @throws SQLException if a database access error occurs + */ + @Override + public int getFetchSize() throws SQLException { + return resultSet.getFetchSize(); + } + + /** + * Sets the number of rows that should be fetched from the database when more rows are needed. + * This can improve performance by reducing the number of database fetch operations. + * + * @param rows the number of rows to fetch. + * @throws SQLException if a database access error occurs or the parameter value is invalid. + */ + @Override + public void setFetchSize(final int rows) throws SQLException { + resultSet.setFetchSize(rows); + } + + /** + * Retrieves the type of the underlying `ResultSet` object. + * + * @return an integer representing the `ResultSet` type. + * @throws SQLException if a database + */ + @Override + public int getType() throws SQLException { + return resultSet.getType(); + } + + /** + * Retrieves the concurrency mode of the result set. + * + * @return an integer representing the concurrency mode of the result set. + * @throws SQLException if a database access error occurs or the result set is closed. + */ + @Override + public int getConcurrency() throws SQLException { + return resultSet.getConcurrency(); + } + + /** + * Checks if the current row of the result set has been updated. + * + * @return true if the current row has been updated and the result set type is a type that detects changes; false otherwise + * @throws SQLException if a database access error occurs or the method is called on a closed result set + */ + @Override + public boolean rowUpdated() throws SQLException { + return resultSet.rowUpdated(); + } + + /** + * Checks whether the current row in the ResultSet was successfully inserted. + * + * @return true if the current row was inserted, false otherwise + * @throws SQLException if a database access error occurs + */ + @Override + public boolean rowInserted() throws SQLException { + return resultSet.rowInserted(); + } + + /** + * Checks whether the current row in the ResultSet has been deleted. + *

+ * This method provides a way to determine if the current row, positioned + * in the ResultSet, has been deleted from the database. It relies on the + * underlying ResultSet's implementation of the rowDeleted method. + * + * @return true if the current row has been deleted and false otherwise + * @throws SQLException if a database access error occurs + */ + @Override + public boolean rowDeleted() throws SQLException { + return resultSet.rowDeleted(); + } + + /** + * Updates the designated column with a SQL NULL value. + * + * @param columnIndex the index of the column to update. The first column is 1, the second is 2, and so on. + * @throws SQLException if a database access error occurs or if the columnIndex is invalid. + */ + @Override + public void updateNull(final int columnIndex) throws SQLException { + resultSet.updateNull(columnIndex); + } + + /** + * Updates the designated column with a boolean value. The update is applied + * to the ResultSet object and can be persisted into the underlying database + * by calling the updateRow method. + * + * @param columnIndex the one-based index of the column to update + * @param x the new boolean value to set in the specified column + * @throws SQLException if the column index is invalid, the ResultSet is closed, + * or a database access error occurs + */ + @Override + public void updateBoolean(final int columnIndex, final boolean x) throws SQLException { + resultSet.updateBoolean(columnIndex, x); + } + + /** + * Updates the designated column with a new byte value. + * + * @param columnIndex the index of the column, starting from 1, where the byte value will be updated + * @param x the new byte value to set in the specified column + * @throws SQLException if a database access error occurs or if this method is called on a closed result set + */ + @Override + public void updateByte(final int columnIndex, final byte x) throws SQLException { + resultSet.updateByte(columnIndex, x); + } + + /** + * Updates the designated column with a short value. + * The update is made to the current row of the ResultSet object. + * + * @param columnIndex the index of the column to update, where the first column is 1 + * @param x the new column value as a short + * @throws SQLException if a database access error occurs, the ResultSet is in read-only mode, + * or the columnIndex is not valid + */ + @Override + public void updateShort(final int columnIndex, final short x) throws SQLException { + resultSet.updateShort(columnIndex, x); + } + + /** + * Updates the designated column with an int value. The updater methods are used to update column + * values in the current row or the insert row. + * + * @param columnIndex the column index (1-based) of the column to update + * @param x the new column value + * @throws SQLException if a database access error occurs or the columnIndex is invalid + */ + @Override + public void updateInt(final int columnIndex, final int x) throws SQLException { + resultSet.updateInt(columnIndex, x); + } + + /** + * Updates the designated column with a long value. + * The updater methods are used to update column values in the current row or the insert row. + * + * @param columnIndex the index of the column to update, starting from 1 + * @param x the new long value to be set in the column + * @throws SQLException if a database access error occurs or if the result set is read-only + */ + @Override + public void updateLong(final int columnIndex, final long x) throws SQLException { + resultSet.updateLong(columnIndex, x); + } + + /** + * Updates the designated column with a float value. + * The updater methods are used to update column values in the current row or the insert row. + * + * @param columnIndex the index of the column to update, starting from 1 + * @param x the new column value as a float + * @throws SQLException if a database access error occurs or if the method is called on a closed result set + */ + @Override + public void updateFloat(final int columnIndex, final float x) throws SQLException { + resultSet.updateFloat(columnIndex, x); + } + + /** + * Updates the designated column with a double value. The column is specified by its index. + * This method must be called on an updatable ResultSet, and the change is only reflected in + * the ResultSet until updateRow() is called to propagate the change to the underlying database. + * + * @param columnIndex the first column is 1, the second is 2, and so on + * @param x the new column value as a double + * @throws SQLException if a database access error occurs or if the column index is not valid + */ + @Override + public void updateDouble(final int columnIndex, final double x) throws SQLException { + resultSet.updateDouble(columnIndex, x); + } + + /** + * Updates the designated column with a BigDecimal value. + * The update is made to the current row of the result set. + * + * @param columnIndex the first column is 1, the second is 2, and so on. + * @param x the new column value as a BigDecimal. A null value indicates + * SQL NULL. + * @throws SQLException if a database access error occurs, this method is + * called on a closed result set, or the ResultSet is + * in an invalid state. + */ + @Override + public void updateBigDecimal(final int columnIndex, final BigDecimal x) throws SQLException { + resultSet.updateBigDecimal(columnIndex, x); + } + + /** + * Updates the designated column with a provided string value. + * This method must be called on a valid column index within the ResultSet. + * + * @param columnIndex the index of the column to update, starting from 1 + * @param x the new string value to set; can be null + * @throws SQLException if a database access error occurs or if the provided index is invalid + */ + @Override + public void updateString(final int columnIndex, final String x) throws SQLException { + resultSet.updateString(columnIndex, x); + } + + /** + * Updates the designated column with a byte array value. The updated value + * will be written to the database when updateRow, insertRow, or deleteRow + * is called. + * + * @param columnIndex the first column is 1, the second is 2, and so on + * @param x the new byte array value for the specified column + * @throws SQLException if the columnIndex is invalid; if a database access + * error occurs; if this method is called on a closed result set; + * or if this method is called in a read-only result set + */ + @Override + public void updateBytes(final int columnIndex, final byte[] x) throws SQLException { + resultSet.updateBytes(columnIndex, x); + } + + /** + * Updates the designated column with a Date object. + * The updater methods are used to update column values in the current row or the insert row. + * + * @param columnIndex the index of the column to update (1-based) + * @param x the new column value as a Date object + * @throws SQLException if a database access error occurs or if the column index is invalid + */ + @Override + public void updateDate(final int columnIndex, final Date x) throws SQLException { + resultSet.updateDate(columnIndex, x); + } + + /** + * Updates the designated column with a {@code Time} value. + * The update is made in the current row of the ResultSet. + * + * @param columnIndex the first column is 1, the second is 2, and so on + * @param x the new column value; must be a {@code Time} object + * @throws SQLException if the column index is invalid, if a database access error occurs, + * or if the ResultSet is in read-only mode + */ + @Override + public void updateTime(final int columnIndex, final Time x) throws SQLException { + resultSet.updateTime(columnIndex, x); + } + + /** + * Updates the designated column with a {@link Timestamp} value. + * + * @param columnIndex the first column is 1, the second is 2, and so on. + * @param x the new column value; can be null to update the column with SQL NULL. + * @throws SQLException if the column index is invalid, this method is called on a closed result set, + * or a database access error occurs. + */ + @Override + public void updateTimestamp(final int columnIndex, final Timestamp x) throws SQLException { + resultSet.updateTimestamp(columnIndex, x); + } + + /** + * Updates the designated column with an ASCII stream value. + * The data in the stream can be read and is then written to the database. + * + * @param columnIndex the index of the column to update, starting from 1 + * @param x the input stream containing the ASCII data to set + * @param length the number of bytes in the input stream to write to the column + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public void updateAsciiStream(final int columnIndex, final InputStream x, final int length) throws SQLException { + resultSet.updateAsciiStream(columnIndex, x, length); + } + + /** + * Updates the designated column with a binary stream value. + * + * @param columnIndex the index of the column to update, where the first column is 1 + * @param x the InputStream containing the binary data to set in the column + * @param length the number of bytes in the InputStream to read and write to the column + * @throws SQLException if a database access error occurs or the columnIndex is invalid + */ + @Override + public void updateBinaryStream(final int columnIndex, final InputStream x, final int length) throws SQLException { + resultSet.updateBinaryStream(columnIndex, x, length); + } + + /** + * Updates the designated column with a character stream value. The data will be read from + * the provided Reader object and written to the database. The number of characters to be written + * is specified by the length parameter. + * + * @param columnIndex the index of the column to be updated, starting from 1 + * @param x the Reader object containing the character data to be written + * @param length the number of characters to be written from the Reader + * @throws SQLException if a database access error occurs or if the columnIndex is invalid + */ + @Override + public void updateCharacterStream(final int columnIndex, final Reader x, final int length) throws SQLException { + resultSet.updateCharacterStream(columnIndex, x, length); + } + + /** + * Updates the designated column with an Object value. The scale or length + * is used for certain types of updates such as updating a numeric value + * or strings where precision or length needs to be specified. + * + * @param columnIndex the index of the column (starting at 1) to be updated + * @param x the new value for the column + * @param scaleOrLength for numeric and string types, this is the precision or + * length to be used; otherwise, ignored + * @throws SQLException if a database access error occurs or if this method + * is called on a closed result set + */ + @Override + public void updateObject(final int columnIndex, final Object x, final int scaleOrLength) throws SQLException { + resultSet.updateObject(columnIndex, x, scaleOrLength); + } + + /** + * Updates the value of the designated column with the given object. + * + * @param columnIndex the index of the column to update, starting from 1 + * @param x the new value for the column, as an Object + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public void updateObject(final int columnIndex, final Object x) throws SQLException { + resultSet.updateObject(columnIndex, x); + } + + /** + * Updates the designated column with a null value. This method is typically used + * when updating database records to explicitly set a column to NULL. + * + * @param columnLabel the label for the column specified with the SQL AS clause. + * If the SQL AS clause was not specified, the column name is used. + * @throws SQLException if a database access error occurs or the result set is not + * updatable. + */ + @Override + public void updateNull(final String columnLabel) throws SQLException { + resultSet.updateNull(columnLabel); + } + + /** + * Updates the designated column with a boolean value. + * + * @param columnLabel the label for the column specified to be updated + * @param x the new boolean value to update the column with + * @throws SQLException if a database access error occurs or the columnLabel is not valid + */ + @Override + public void updateBoolean(final String columnLabel, final boolean x) throws SQLException { + resultSet.updateBoolean(columnLabel, x); + } + + /** + * Updates the designated column with a byte value. The update is applied to the current row + * of the ResultSet object. + * + * @param columnLabel the label for the column to be updated. It must match the column name as + * defined in the database table. + * @param x the new byte value that will be assigned to the specified column. + * @throws SQLException if a database access error occurs, the column label is not valid, or + * the ResultSet is in read-only mode. + */ + @Override + public void updateByte(final String columnLabel, final byte x) throws SQLException { + resultSet.updateByte(columnLabel, x); + } + + /** + * Updates the designated column with a short value. + * The updated value is not immediately written to the database but is cached in the ResultSet until {@code updateRow()} is called. + * + * @param columnLabel the label for the column to be updated + * @param x the new column value as a short + * @throws SQLException if a database access error occurs, this method is called on a closed ResultSet, + * or if the columnLabel is not valid + */ + @Override + public void updateShort(final String columnLabel, final short x) throws SQLException { + resultSet.updateShort(columnLabel, x); + } + + /** + * Updates the designated column with the specified integer value. + * This method is used to update the value of a column in the current row + * of the ResultSet object. The column is specified by its label. + * + * @param columnLabel the label for the column to be updated + * @param x the new integer value for the column + * @throws SQLException if a database access error occurs or the result set + * is not updatable + */ + @Override + public void updateInt(final String columnLabel, final int x) throws SQLException { + resultSet.updateInt(columnLabel, x); + } + + /** + * Updates the designated column with a specified long value. The updater methods are used + * to update column values in the current row or the insert row + */ + @Override + public void updateLong(final String columnLabel, final long x) throws SQLException { + resultSet.updateLong(columnLabel, x); + } + + /** + * Updates the designated column with a float value. The update is applied to + * the current row of the ResultSet object. + * + * @param columnLabel the label for the column that is to be updated + * @param x the new column value as a float + * @throws SQLException if an error occurs while updating the column or if the + * ResultSet is in an invalid state for the update + */ + @Override + public void updateFloat(final String columnLabel, final float x) throws SQLException { + resultSet.updateFloat(columnLabel, x); + } + + /** + * Updates the designated column with a specified double value. + * + * @param columnLabel the label for the column specified, which is the name of the column + * @param x the new column value as a double + * @throws SQLException if a database access error occurs, the result set is closed, + * or the columnLabel is not valid + */ + @Override + public void updateDouble(final String columnLabel, final double x) throws SQLException { + resultSet.updateDouble(columnLabel, x); + } + + /** + * Updates the designated column with a {@code BigDecimal} value. + * The update is made to the underlying database as well as to the + * {@code ResultSet} object. + * + * @param columnLabel the label of the column to update + * @param x the new {@code BigDecimal} value to assign to the column; + * can be {@code null} + * @throws SQLException if a database access error occurs + */ + @Override + public void updateBigDecimal(final String columnLabel, final BigDecimal x) throws SQLException { + resultSet.updateBigDecimal(columnLabel, x); + } + + /** + * Updates the designated column with a new String value. + * The update is applicable to the current row of the ResultSet. + * + * @param columnLabel the label for the column to be updated + * @param x the new String value to update the column with + * @throws SQLException if a database access error occurs, + * the columnLabel is not valid or the ResultSet is in an invalid state + */ + @Override + public void updateString(final String columnLabel, final String x) throws SQLException { + resultSet.updateString(columnLabel, x); + } + + /** + * Updates the designated column with a byte array value. + * The updateBytes method should be used when updating columns in + * a ResultSet that is updateable. + * + * @param columnLabel the label for the column to be updated + * @param x the new column value stored as a byte array + * @throws SQLException if a database access error occurs or the ResultSet cannot be updated + */ + @Override + public void updateBytes(final String columnLabel, final byte[] x) throws SQLException { + resultSet.updateBytes(columnLabel, x); + } + + /** + * Updates the designated column with a Date value. This method is used to update + * the value of a specified column in the current row of the ResultSet with a Date object. + * + * @param columnLabel the label for the column specified with the SQL AS clause. + * If the SQL AS clause was not specified, the label is the name of the column. + * @param x the new Date value to update the specified column with. This value can be null. + * @throws SQLException if a database access error occurs or the ResultSet is in read-only mode. + */ + @Override + public void updateDate(final String columnLabel, final Date x) throws SQLException { + resultSet.updateDate(columnLabel, x); + } + + /** + * Updates the designated column with a {@code Time} value. + * The update is made to the current row of the {@link ResultSet} object. + * + * @param columnLabel the label of the column to be updated + * @param x the new column {@code Time} value + * @throws SQLException if a database access error occurs or the columnLabel + * is not valid + */ + @Override + public void updateTime(final String columnLabel, final Time x) throws SQLException { + resultSet.updateTime(columnLabel, x); + } + + /** + * Updates the designated column with a Timestamp value. + * This method updates the column denoted by the specified column label + * in the current row of this ResultSet object. + * + * @param columnLabel the label for the column to be updated + * @param x the new column value as a Timestamp object; may be null + * @throws SQLException if a database access error occurs, the ResultSet is closed, + * or if the provided column label does not exist + */ + @Override + public void updateTimestamp(final String columnLabel, final Timestamp x) throws SQLException { + resultSet.updateTimestamp(columnLabel, x); + } + + /** + * Updates the designated column with an ASCII stream value. + * The input stream must contain ASCII characters. The stream must be fully read before + * setting the value to the designated column. + * + * @param columnLabel the label for the column to be updated + * @param x the input stream containing the ASCII data + * @param length the number of bytes in the input stream + * @throws SQLException if a database access error occurs or the columnLabel is not valid + */ + @Override + public void updateAsciiStream(final String columnLabel, final InputStream x, final int length) throws SQLException { + resultSet.updateAsciiStream(columnLabel, x, length); + } + + /** + * Updates the designated column with a binary input stream containing the specified number of bytes. + * This method is used to store binary data into a column. + * + * @param columnLabel the label for the column specified with the update + * @param x the InputStream object that contains the binary data to be written + * @param length the number of bytes in the InputStream to be written to the column + * @throws SQLException if a database access error occurs or the columnLabel is not valid + */ + @Override + public void updateBinaryStream(final String columnLabel, final InputStream x, final int length) throws SQLException { + resultSet.updateBinaryStream(columnLabel, x, length); + } + + /** + * Updates the designated column with a character stream value. The character stream will have + * a specified length in characters. + * + * @param columnLabel the label of the column to update + * @param reader the java.io.Reader object that contains the character stream + * @param length the number of characters in the input stream + * @throws SQLException if a database access error occurs or the value is invalid + */ + @Override + public void updateCharacterStream(final String columnLabel, final Reader reader, final int length) throws SQLException { + resultSet.updateCharacterStream(columnLabel, reader, length); + } + + /** + * Updates the designated column with an object value. The update is applied to + * the specified column in the current row of this ResultSet object. + * + * @param columnLabel the label for the column specified with the update + * @param x the new column value, which must be an instance of a class supported by the JDBC driver + * or null to set the column value to SQL NULL + * @param scaleOrLength for an input parameter of SQL type DECIMAL or NUMERIC, this is the + * number of digits after the decimal point. For Java Object types + * InputStream and Reader, this is the length of the data in the stream or reader. + * For all other types, this value will be ignored. + * @throws SQLException if a database access error occurs or this method is called on a closed ResultSet + */ + @Override + public void updateObject(final String columnLabel, final Object x, final int scaleOrLength) throws SQLException { + resultSet.updateObject(columnLabel, x, scaleOrLength); + } + + /** + * Updates the designated column with an Object value. + * The update is applied to the current row of the ResultSet, and will be written to the database + * when the ResultSet is updated. + * + * @param columnLabel the label of the column to be updated + * @param x the new column value to be set, which can be any object type + * @throws SQLException if a database access error occurs or if the columnLabel is not valid + */ + @Override + public void updateObject(final String columnLabel, final Object x) throws SQLException { + resultSet.updateObject(columnLabel, x); + } + + /** + * Inserts the current row into the database. + *

+ * This method delegates the call to {@link ResultSet#insertRow()}. + * The method inserts the contents of the insert row into the database. + * It must be called while the cursor is positioned on the insert row. + * After the insertion, the cursor will remain positioned on the insert row. + * + * @throws SQLException if a database access error occurs or if this method + * is called when the cursor is not on the insert row. + */ + @Override + public void insertRow() throws SQLException { + resultSet.insertRow(); + } + + /** + * Updates the current row in the database using the current values of the + * ResultSet. This method writes any changes made to the result set to + * the database. + * + * @throws SQLException if a database access error occurs, the ResultSet + * is in read-only mode, or if this method is called on a + * ResultSet that is not positioned on a valid row. + */ + @Override + public void updateRow() throws SQLException { + resultSet.updateRow(); + } + + /** + * Deletes the current row from the database. + * This method removes the current row in the ResultSet object + * and the corresponding row in the database. + * + * @throws SQLException if a database access error occurs, + * the current row is not valid, or the ResultSet object is + * not updatable. + */ + @Override + public void deleteRow() throws SQLException { + resultSet.deleteRow(); + } + + /** + * Refreshes the current row of the ResultSet object to reflect the most recent + * changes made to the database. This method is particularly useful when + * concurrent updates are made to the underlying database, allowing the ResultSet + * to synchronize its data with the latest state of the database row. + * + * @throws SQLException if a database access error occurs or if the ResultSet + * is closed. + */ + @Override + public void refreshRow() throws SQLException { + resultSet.refreshRow(); + } + + /** + * Cancels the updates made to the current row in this ResultSet object. + *

+ * If the cancelRowUpdates method is called, the updates made to the current row + * will be discarded and no changes will be applied when the ResultSet is updated. + *

+ * This method delegates the call to the wrapped ResultSet's cancelRowUpdates method. + * + * @throws SQLException if a database access error occurs or this method is called + * on a closed ResultSet. + */ + @Override + public void cancelRowUpdates() throws SQLException { + resultSet.cancelRowUpdates(); + } + + /** + * Moves the cursor to the insert row of the ResultSet object. + * The insert row is a special row associated with a ResultSet + * object that is used as a staging ground for building a row + * to be inserted. Only columns with a defined value can be updated + * when on the insert row. + *

+ * This method provides a convenient way to prepare a row for insert + * operations. After setting the desired column values using the + * appropriate updater methods, the row can be committed to the + * database using the `insertRow` method of the ResultSet. + * + * @throws SQLException if a database access error occurs or + * if this method is called on a closed ResultSet. + */ + @Override + public void moveToInsertRow() throws SQLException { + resultSet.moveToInsertRow(); + } + + /** + * Moves the cursor to the remembered cursor position, usually the position + * where the cursor was located prior to calling the {@code moveToInsertRow} method. + * This method is typically used when working with updatable result sets, allowing the + * cursor to return to its previous position after inserting a row. + * + * @throws SQLException if a database access error occurs or this method is + * called on a ResultSet object that is not updatable. + */ + @Override + public void moveToCurrentRow() throws SQLException { + resultSet.moveToCurrentRow(); + } + + /** + * Retrieves the Statement object that produced this ResultSet object. + * + * @return the Statement object that produced this ResultSet or null if the result set was generated + * by a DatabaseMetaData method or if this method is called on a closed result set. + * @throws SQLException if a database access error occurs or this method is called on a closed result set. + */ + @Override + public Statement getStatement() throws SQLException { + return resultSet.getStatement(); + } + + /** + * Updates the designated column with an ASCII stream value. + * The data will be read from the provided InputStream and should match the specified length. + * This method can be used to update a column in the current row of a ResultSet object. + * + * @param columnIndex the index of the column to update, starting from 1 + * @param x the InputStream object containing the ASCII stream data + * @param length the length of the ASCII stream in bytes + * @throws SQLException if a database access error occurs or the ResultSet is not updatable + */ + @Override + public void updateAsciiStream(final int columnIndex, final InputStream x, final long length) throws SQLException { + resultSet.updateAsciiStream(columnIndex, x, length); + } + + /** + * Updates the designated column with a binary stream value. The data will be read from the given + * InputStream object starting from the current position to the specified length. The stream must + * provide at least the number of bytes specified by the length parameter. + * + * @param columnIndex the index of the column to update (1-based index) + * @param x the InputStream containing the binary data + * @param length the number of bytes to write from the InputStream + * @throws SQLException if a database access error occurs or if any argument is invalid + */ + @Override + public void updateBinaryStream(final int columnIndex, final InputStream x, final long length) throws SQLException { + resultSet.updateBinaryStream(columnIndex, x, length); + } + + /** + * Updates the designated column with a character stream value. + * The data will be read from the provided Reader object. + * + * @param columnIndex the 1-based index of the column to update + * @param x the Reader object that contains the new character stream value + * @param length the number of characters in the stream + * @throws SQLException if a database access error occurs, the column index is out of bounds, + * or if the provided Reader is null + */ + @Override + public void updateCharacterStream(final int columnIndex, final Reader x, final long length) throws SQLException { + resultSet.updateCharacterStream(columnIndex, x, length); + } + + /** + * Updates the designated column with an ASCII stream value. The stream must contain + * ASCII characters and is read to the specified number of characters. If the designated + * column does not support ASCII stream updates, a SQLException will be thrown. + * + * @param columnLabel the label of the column to be updated + * @param x the InputStream containing the ASCII data + * @param length the number of bytes to read from the InputStream + * @throws SQLException if a database access error occurs, if the columnLabel does not exist, + * or if this method is called on a closed result set + */ + @Override + public void updateAsciiStream(final String columnLabel, final InputStream x, final long length) throws SQLException { + resultSet.updateAsciiStream(columnLabel, x, length); + } + + /** + * Updates the designated column with a binary stream value. + * The data will be read from the supplied {@code InputStream} and written to the column, + * according to the specified length. + * + * @param columnLabel the label for the column to be updated + * @param x the {@code InputStream} object that contains the new column value + * @param length the number of bytes in the stream to read + * @throws SQLException if a database access error occurs or if the columnLabel is not valid + */ + @Override + public void updateBinaryStream(final String columnLabel, final InputStream x, final long length) throws SQLException { + resultSet.updateBinaryStream(columnLabel, x, length); + } + + /** + * Updates the designated column with a character stream value. + * The data in the stream will have the specified length. + * + * @param columnLabel the label for the column name + * @param reader the java.io.Reader object that contains the data to set the column value to + * @param length the number of characters in the stream + * @throws SQLException if the columnLabel is not valid, a database access error occurs, + * the result set is closed, or if this method is called on a read-only result set + */ + @Override + public void updateCharacterStream(final String columnLabel, final Reader reader, final long length) throws SQLException { + resultSet.updateCharacterStream(columnLabel, reader, length); + } + + /** + * Updates the designated column with a {@link Blob} value. + *

+ * The updateBlob method updates the current row's column with the + * specified Blob object. The update is not persisted in the database + * until the {@code updateRow()} method is called. + * + * @param columnIndex the index of the column to update, starting from 1 + * @param x the new Blob value to assign to the column + * @throws SQLException if a database access error occurs or the result set + * is not updatable + */ + @Override + public void updateBlob(final int columnIndex, final Blob x) throws SQLException { + resultSet.updateBlob(columnIndex, x); + } + + /** + * Updates the designated column with a Blob value. The updater methods are + * used to update column values in the current row or the insert row. The + * update is not applied to the database until the method `updateRow` is called. + * + * @param columnLabel the label for the column specified with the SQL query. + * @param x the Blob object that contains the data to set the value in the specified column. + * @throws SQLException if a database access error occurs or this method is + * called on a closed ResultSet. + */ + @Override + public void updateBlob(final String columnLabel, final Blob x) throws SQLException { + resultSet.updateBlob(columnLabel, x); + } + + /** + * Updates the designated column with a Clob value. The column is specified by its index, + * and the value is provided as a Clob object. This method updates the Clob value on the + * underlying database structure. + * + * @param columnIndex the index of the column to update, starting from 1. + * @param x the Clob object containing the new value to set for the specified column. + * @throws SQLException if a database access error occurs or the operation is not supported. + */ + @Override + public void updateClob(final int columnIndex, final Clob x) throws SQLException { + resultSet.updateClob(columnIndex, x); + } + + /** + * Updates the designated column with a Clob value. The updater methods are used to update column + * values in the result set, which can then be updated in the underlying database. + * + * @param columnLabel the label for the column specified in the SQL query + * @param x the Clob value to update the column with + * @throws SQLException if a database access error occurs or the result set is in read-only mode + */ + @Override + public void updateClob(final String columnLabel, final Clob x) throws SQLException { + resultSet.updateClob(columnLabel, x); + } + + /** + * Updates the designated column with an Array value. + * + * @param columnIndex the index of the column to be updated, where the first column is 1 + * @param x the new Array value to update the column with + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public void updateArray(final int columnIndex, final Array x) throws SQLException { + resultSet.updateArray(columnIndex, x); + } + + /** + * Updates the designated column with an Array value. + * + * @param columnLabel the label for the column to be updated + * @param x the Array object to update the column with + * @throws SQLException if a database access error occurs or the columnLabel is invalid + */ + @Override + public void updateArray(final String columnLabel, final Array x) throws SQLException { + resultSet.updateArray(columnLabel, x); + } + + /** + * Retrieves the RowId object that corresponds to the specified column index in the result set. + * + * @param columnIndex the column index, starting from 1, for which the RowId is to be retrieved + * @return the RowId value for the specified column index + * @throws SQLException if a database access error occurs or the columnIndex is invalid + */ + @Override + public RowId getRowId(final int columnIndex) throws SQLException { + return resultSet.getRowId(columnIndex); + } + + /** + * Retrieves the RowId object corresponding to the specified column label. + * + * @param columnLabel the label for the column from which to retrieve the RowId + * @return the RowId object for the specified column + * @throws SQLException if a database access error occurs or the column label is invalid + */ + @Override + public RowId getRowId(final String columnLabel) throws SQLException { + return resultSet.getRowId(columnLabel); + } + + /** + * Updates the designated column with a RowId value. + * The updateRowId method provides the capability to update the column with a RowId object + * which represents the SQL ROWID data type. The update is performed for the current row + * of the ResultSet. + * + * @param columnIndex the 1-based index of the column to be updated + * @param x the RowId object containing the new value for the column + * @throws SQLException if a database access error occurs or the result set is not updatable + */ + @Override + public void updateRowId(final int columnIndex, final RowId x) throws SQLException { + resultSet.updateRowId(columnIndex, x); + } + + /** + * Updates the designated column with a new RowId value. + * + * @param columnLabel the label for the column specified by the SQL AS clause. + * If the SQL AS clause was not specified, the name of the column is used. + * @param x the new RowId value to update in the specified column + * @throws SQLException if a database access error occurs or the method is called on a closed ResultSet + */ + @Override + public void updateRowId(final String columnLabel, final RowId x) throws SQLException { + resultSet.updateRowId(columnLabel, x); + } + + /** + * Retrieves the current holdability of ResultSet objects created using this method. + * + * @return an integer representing the holdability of ResultSet objects. The value is + * either ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT. + * @throws SQLException if a database access error occurs. + */ + @Override + public int getHoldability() throws SQLException { + return resultSet.getHoldability(); + } + + /** + * Checks if the {@code ResultSet} is closed. + * + * @return {@code true} if the {@code ResultSet} is closed; {@code false} otherwise. + * @throws SQLException if a database access error occurs. + */ + @Override + public boolean isClosed() throws SQLException { + return resultSet.isClosed(); + } + + /** + * Updates the designated column with a String value. The column index specifies + * the column to be updated, and the String value provided will be stored in the + * appropriate column of the underlying database. + * + * @param columnIndex the first column is 1, the second is 2, and so on + * @param nString the new value for the designated column. Can be null. + * @throws SQLException if a database access error occurs or this method is + * called on a closed ResultSet + */ + @Override + public void updateNString(final int columnIndex, final String nString) throws SQLException { + resultSet.updateNString(columnIndex, nString); + } + + /** + * Updates the designated column with the given string value. The updateNString method should + * be used when the column stores a national character set value. + * + * @param columnLabel the label for the column to be updated + * @param nString the new column value of type String + * @throws SQLException if a database access error occurs or if the method is called on a closed result set + */ + @Override + public void updateNString(final String columnLabel, final String nString) throws SQLException { + resultSet.updateNString(columnLabel, nString); + } + + /** + * Updates the designated column with a given NClob value. + * Updates the NClob object in the ResultSet to reflect changes. + * + * @param columnIndex the column index in the ResultSet, starting at 1, which needs to be updated + * @param nClob the NClob object that holds the new value to assign to the column + * @throws SQLException if a database access error occurs or the ResultSet is in a read-only state + */ + @Override + public void updateNClob(final int columnIndex, final NClob nClob) throws SQLException { + resultSet.updateNClob(columnIndex, nClob); + } + + /** + * Updates the designated column with a given NClob object. The column is specified by + * its label, and the input NClob object will be used to update the value in the + * ResultSet. This method can be used to update NClob data in a database. + * + * @param columnLabel the label for the column to be updated + * @param nClob the NClob object containing the data to update the column with + * @throws SQLException if a database access error occurs or this method is called + * on a closed ResultSet + */ + @Override + public void updateNClob(final String columnLabel, final NClob nClob) throws SQLException { + resultSet.updateNClob(columnLabel, nClob); + } + + /** + * Retrieves the value of the specified column as a {@code NClob} object. + * + * @param columnIndex the index of the column from which the value is to be retrieved, + * starting at 1 for the first column. + * @return the {@code NClob} object representing the value of the specified column, + * or {@code null} if the column contains SQL {@code NULL}. + * @throws SQLException if a database access error occurs or if the column index is invalid. + */ + @Override + public NClob getNClob(final int columnIndex) throws SQLException { + return resultSet.getNClob(columnIndex); + } + + /** + * Retrieves the value of the designated column as a {@link NClob} object. + * + * @param columnLabel the label for the column specified with the SQL AS clause. + * If the SQL AS clause was not specified, then the label is the name of the column. + * @return the value of the designated column as a {@link NClob} object; + * if the value is SQL NULL, the method returns null. + * @throws SQLException if a database access error occurs or this method is called on a closed result set. + */ + @Override + public NClob getNClob(final String columnLabel) throws SQLException { + return resultSet.getNClob(columnLabel); + } + + /** + * Retrieves the value of the designated column in the current row of this + * ResultSet object as a SQLXML object. + * + * @param columnIndex the column index, starting from 1 for the first column + * @return the SQLXML value of the specified column in the current row + * @throws SQLException if a database access error occurs or the column index is not valid + */ + @Override + public SQLXML getSQLXML(final int columnIndex) throws SQLException { + return resultSet.getSQLXML(columnIndex); + } + + /** + * Retrieves the value of the designated column as a {@code SQLXML} object. + * + * @param columnLabel the label for the column specified in the query. + * @return the {@code SQLXML} object representing the SQL XML value of the specified column. + * @throws SQLException if there is an error accessing the SQL data or if the column does not support SQLXML values. + */ + @Override + public SQLXML getSQLXML(final String columnLabel) throws SQLException { + return resultSet.getSQLXML(columnLabel); + } + + /** + * Updates the designated column with the given SQLXML value. + * + * @param columnIndex the first column is 1, the second is 2, and so on. + * @param xmlObject the SQLXML object representing the XML value to update the column with. + * @throws SQLException if a database access error occurs or if the columnIndex is invalid. + */ + @Override + public void updateSQLXML(final int columnIndex, final SQLXML xmlObject) throws SQLException { + resultSet.updateSQLXML(columnIndex, xmlObject); + } + + /** + * Updates the designated column with an SQLXML value. The update is performed + * on the current row of the ResultSet. + * + * @param columnLabel the label for the column specified with the SQL XML data type. + * @param xmlObject the SQLXML object containing the data to set in the specified column. + * @throws SQLException if an error occurs while updating the SQLXML value or if the ResultSet is in read-only mode. + */ + @Override + public void updateSQLXML(final String columnLabel, final SQLXML xmlObject) throws SQLException { + resultSet.updateSQLXML(columnLabel, xmlObject); + } + + /** + * Updates the designated column with a character stream value. The data will be read + * from the provided Reader object and should have a specified length. + * + * @param columnIndex the column index (1-based) indicating the column to be updated + * @param x the Reader object that contains the new character stream data + * @param length the number of characters in the stream to be read + * @throws SQLException if a database access error occurs or the columnIndex is invalid + */ + @Override + public void updateNCharacterStream(final int columnIndex, final Reader x, final long length) throws SQLException { + resultSet.updateNCharacterStream(columnIndex, x, length); + } + + /** + * Updates the designated column with a character stream value. + * The data will be read from the provided Reader and will have the specified length. + * + * @param columnLabel the label for the column to update + * @param reader the java.io.Reader object from which the data will be read + * @param length the length of the stream in characters + * @throws SQLException if a database access error occurs or the column label is invalid + */ + @Override + public void updateNCharacterStream(final String columnLabel, final Reader reader, final long length) throws SQLException { + resultSet.updateNCharacterStream(columnLabel, reader, length); + } + + /** + * Updates the designated column with a character stream value. The data will be read from the provided + * Reader object and used to update the column indicated by the columnIndex parameter. + * + * @param columnIndex the index of the column to update, where the first column is 1 + * @param x the Reader object that contains the new character stream data + * @throws SQLException if a database access error occurs or the result set is in a read-only mode + */ + @Override + public void updateNCharacterStream(final int columnIndex, final Reader x) throws SQLException { + resultSet.updateNCharacterStream(columnIndex, x); + } + + /** + * Updates the designated column with a character stream value, which will then + * be written to the database. The column specified by the given label will be updated + * with the data provided by the Reader object. + * + * @param columnLabel the label for the column that needs to be updated. + * @param reader the java.io.Reader object containing the data to set the column value. + * @throws SQLException if a database access error occurs or the columnLabel is invalid. + */ + @Override + public void updateNCharacterStream(final String columnLabel, final Reader reader) throws SQLException { + resultSet.updateNCharacterStream(columnLabel, reader); + } + + /** + * Updates the designated column with a binary stream value, which will have + * the specified number of bytes. The data will be read from the provided + * {@code InputStream}. + * + * @param columnIndex the first column is 1, the second is 2, ... + * @param inputStream the {@code InputStream} object containing the binary data + * @param length the number of bytes in the binary data + * @throws SQLException if a database access error occurs or if the column + * index is invalid + */ + @Override + public void updateBlob(final int columnIndex, final InputStream inputStream, final long length) throws SQLException { + resultSet.updateBlob(columnIndex, inputStream, length); + } + + /** + * Updates the designated column with an InputStream value, which will be written to the database as a Blob. + * + * @param columnLabel the label for the column to be updated + * @param inputStream the InputStream containing the Blob data + * @param length the number of bytes in the InputStream + * @throws SQLException if a database access error occurs or the columnLabel is invalid + */ + @Override + public void updateBlob(final String columnLabel, final InputStream inputStream, final long length) throws SQLException { + resultSet.updateBlob(columnLabel, inputStream, length); + } + + /** + * Updates the designated column with a binary stream value. + * The input stream is used to supply the binary data for the value to be set in the column. + * + * @param columnIndex the first column is 1, the second is 2, and so on + * @param inputStream the InputStream containing the binary data to set + * @throws SQLException if the columnIndex is invalid, if a database access error occurs, + * or if this method is called on a closed result set + */ + @Override + public void updateBlob(final int columnIndex, final InputStream inputStream) throws SQLException { + resultSet.updateBlob(columnIndex, inputStream); + } + + /** + * Updates the designated column with an InputStream value, which will be + * set as a BLOB in the underlying database. + * + * @param columnLabel the label for the column whose value will be set + * @param inputStream the InputStream containing the binary data to set as a BLOB + * @throws SQLException if a database access error occurs or the specified + * columnLabel is not valid + */ + @Override + public void updateBlob(final String columnLabel, final InputStream inputStream) throws SQLException { + resultSet.updateBlob(columnLabel, inputStream); + } + + /** + * Updates the designated column with a Clob value. The data will be read from the provided Reader + * object for the specified number of characters. + * + * @param columnIndex the index of the column to update, starting from 1 + */ + @Override + public void updateClob(final int columnIndex, final Reader reader, final long length) throws SQLException { + resultSet.updateClob(columnIndex, reader, length); + } + + /** + * Updates the designated column with a character stream containing a CLOB value. + * The data in the stream will be read into the CLOB value, starting at the beginning. + * The length parameter indicates the number of characters to read from the reader. + * + * @param columnLabel the label for the column specified with the SQL AS clause + * or the column name + * @param reader the java.io.Reader object containing the data to set as the CLOB value + * @param length the length of the data to be written to the CLOB column in characters + * @throws SQLException if a database access error occurs, this method is called on a closed result set, + * if the designated column does not have a CLOB data type, + * or if the length specified is invalid + */ + @Override + public void updateClob(final String columnLabel, final Reader reader, final long length) throws SQLException { + resultSet.updateClob(columnLabel, reader, length); + } + + /** + * Updates the designated Clob column using the data provided by a Reader object. + * The new data will overwrite the existing Clob value at the specified column index. + * + * @param columnIndex the index of the column to be updated, starting from 1 + * @param reader the Reader object that contains the new Clob data to set + * @throws SQLException if a database access error occurs or the column index is invalid + */ + @Override + public void updateClob(final int columnIndex, final Reader reader) throws SQLException { + resultSet.updateClob(columnIndex, reader); + } + + /** + * Updates the designated Clob column with the given character stream reader. + * + * @param columnLabel the label for the column specified with a SQL identifier + * @param reader the Reader object that contains the new Clob data + * @throws SQLException if a database access error occurs or the columnLabel is not valid + */ + @Override + public void updateClob(final String columnLabel, final Reader reader) throws SQLException { + resultSet.updateClob(columnLabel, reader); + } + + /** + * Updates the designated column with a character stream value, which will have + * a specified number of characters, in the current row of this ResultSet object. + * + * @param columnIndex the column index (starting from 1) indicating the column to be updated + * @param reader the java.io.Reader object that contains the data to be written to the NClob column + * @param length the number of characters in the stream to be written to the column + * @throws SQLException if a database access error occurs, second parameter is null, or this method is + * called on a closed ResultSet + */ + @Override + public void updateNClob(final int columnIndex, final Reader reader, final long length) throws SQLException { + resultSet.updateNClob(columnIndex, reader, length); + } + + /** + * Updates the designated column with a new CLOB value. The data will be read from the supplied Reader + * and will have the specified length. The column is identified using its label. + * + * @param columnLabel the label for the column to be updated + * @param reader the Reader object that contains the data to update the CLOB value + * @param length the number of characters in the Reader to be read + * @throws SQLException if a database access error occurs or the columnLabel is not valid + */ + @Override + public void updateNClob(final String columnLabel, final Reader reader, final long length) throws SQLException { + resultSet.updateNClob(columnLabel, reader, length); + } + + /** + * Updates the designated NClob column with a Reader object. The data in the Reader object + * will be written to the NClob value that is being updated. This method is typically used + * when working with large NClob data. + * + * @param columnIndex the index of the column to update (1-based index) + * @param reader the java.io.Reader object containing the data to set the NClob value + * @throws SQLException if a database access error occurs or the method is called on + * a closed ResultSet + */ + @Override + public void updateNClob(final int columnIndex, final Reader reader) throws SQLException { + resultSet.updateNClob(columnIndex, reader); + } + + /** + * Updates the designated column with a new NClob value. The data is read + * from the provided Reader object. + * + * @param columnLabel the label for the column to be updated + * @param reader the java.io.Reader object from which the NClob value will be read + * @throws SQLException if a database access error occurs or the Reader object is null + */ + @Override + public void updateNClob(final String columnLabel, final Reader reader) throws SQLException { + resultSet.updateNClob(columnLabel, reader); + } + + /** + * Retrieves an object from the specified column index in the result set and converts it to the specified type. + * + * @param the type of the object to be retrieved + * @param columnIndex the index of the column from which the object is to be retrieved, starting at 1 + * @param type the Class object representing the type to which the object should be converted + * @return the object from the specified column converted to the specified type + * @throws SQLException if a database access error occurs or this method is called on a closed result set + */ + @Override + public T getObject(final int columnIndex, final Class type) throws SQLException { + return resultSet.getObject(columnIndex, type); + } + + /** + * Retrieves an object from the specified column label in the result set and casts it to the provided type. + * + * @param columnLabel the label for the column from which the object will be retrieved + * @param type the class of the object to be retrieved + * @return the object retrieved from the specified column, cast to the specified type + * @throws SQLException if a database access error occurs or the column label is not valid + */ + @Override + public T getObject(final String columnLabel, final Class type) throws SQLException { + return resultSet.getObject(columnLabel, type); + } + + /** + * Updates the designated column with an object value. The update will be applied to the column + * specified by the given column index. This method allows specifying a SQL target type and a scale + * or length for the object being updated. + * + * @param columnIndex the index of the column to update + */ + @Override + public void updateObject(final int columnIndex, final Object x, final SQLType targetSqlType, final int scaleOrLength) + throws SQLException { + resultSet.updateObject(columnIndex, x, targetSqlType, scaleOrLength); + } + + /** + * Updates the designated column with an object value. + * The object will be converted to the specified SQL type before being updated. + * + * @param columnLabel the label for the column to be updated + * @param x the object containing the value to be stored in the specified column + * @param targetSqlType the SQL type to convert the object to + * @param scaleOrLength for numeric data, this is the number of digits after the decimal point; + * for non-numeric data, this is the length of the data + * @throws SQLException if a database access error occurs, this method is called on a closed ResultSet, + * or the target SQL type is invalid + */ + @Override + public void updateObject(final String columnLabel, final Object x, final SQLType targetSqlType, final int scaleOrLength) + throws SQLException { + resultSet.updateObject(columnLabel, x, targetSqlType, scaleOrLength); + } + + /** + * Updates the designated column with an object value. The update is made to + * the current row of the ResultSet object. This method allows specifying + * the column index and the target SQL type for the object being updated. + * + * @param columnIndex the index of the column to update, starting from 1 + * @param x the object containing the new column value + * @param targetSqlType the SQL type to be sent to the database + * @throws SQLException if a database access error occurs or if the specified + * parameters are invalid + */ + @Override + public void updateObject(final int columnIndex, final Object x, final SQLType targetSqlType) throws SQLException { + resultSet.updateObject(columnIndex, x, targetSqlType); + } + + /** + * Updates the value of the designated column with the given column label in the current row of this + * ResultSet object to the provided Java object. The data will be converted to the SQL type specified + * by the given targetSqlType parameter before updating. + * + * @param columnLabel the label for the column to be updated + * @param x the new column value + * @param targetSqlType the SQL type to be used for data conversion before updating + * @throws SQLException if a database access error occurs or if the columnLabel is not valid + */ + @Override + public void updateObject(final String columnLabel, final Object x, final SQLType targetSqlType) throws SQLException { + resultSet.updateObject(columnLabel, x, targetSqlType); + } + + /** + * Updates the designated column with an ASCII InputStream. + * The stream must contain only ASCII characters. The driver reads the stream to the end. + * + * @param columnIndex the index of the column to update, starting from 1. + * @param x the InputStream containing ASCII data to set in the specified column. + * @throws SQLException if a database access error occurs or the columnIndex is invalid. + */ + @Override + public void updateAsciiStream(final int columnIndex, final InputStream x) throws SQLException { + resultSet.updateAsciiStream(columnIndex, x); + } + + /** + * Updates the designated column with a binary stream value. + * The data provided in the stream replaces the existing value of the column + * at the specified index in the current row of the ResultSet. + * + * @param columnIndex the index of the column to be updated, where the first column is 1 + * @param x the InputStream containing the binary data to set in the column + * @throws SQLException if a database access error occurs or the ResultSet is in a state + * that does not permit the update + */ + @Override + public void updateBinaryStream(final int columnIndex, final InputStream x) throws SQLException { + resultSet.updateBinaryStream(columnIndex, x); + } + + /** + * Updates the designated column with a new character stream value. + * The data will be read from the provided Reader object and written to the database. + * + * @param columnIndex the index of the column to be updated, starting from 1 + * @param x the Reader object containing the new character stream value + * @throws SQLException if a database access error occurs or the columnIndex is invalid + */ + @Override + public void updateCharacterStream(final int columnIndex, final Reader x) throws SQLException { + resultSet.updateCharacterStream(columnIndex, x); + } + + /** + * Updates the designated column with an ASCII stream. + * The data will be read from the input stream as needed until the end of the stream is reached. + * This method can be used to update columns in the current row or the insert row. + * + * @param columnLabel the label for the column specified with the SQL AS clause. + * If the SQL AS clause was not specified, the label will default to the column name. + * @param x the InputStream object containing the ASCII stream data to set in the column + * @throws SQLException if a database access error occurs, this method is called on a closed result set, + * or if the ResultSet concurrency is CONCUR_READ_ONLY + */ + @Override + public void updateAsciiStream(final String columnLabel, final InputStream x) throws SQLException { + resultSet.updateAsciiStream(columnLabel, x); + } + + /** + * Updates the designated column with a binary stream value. The column is specified by the column label. + * The data in the InputStream can be used as an updated value for the column. + * + * @param columnLabel the label for the column to be updated. + * @param x the InputStream containing the binary stream data to update the column with. + * @throws SQLException if a database access error occurs or the column label is not valid. + */ + @Override + public void updateBinaryStream(final String columnLabel, final InputStream x) throws SQLException { + resultSet.updateBinaryStream(columnLabel, x); + } + + /** + * Updates the designated column with a new character stream value. + * The data will be read from the provided Reader object and sent to the database. + * + * @param columnLabel the label for the column that is to be updated + * @param reader the Reader object containing the data to set the specified column to + * @throws SQLException if a database access error occurs, this method is called on a closed result set, + * or the columnLabel is invalid + */ + @Override + public void updateCharacterStream(final String columnLabel, final Reader reader) throws SQLException { + resultSet.updateCharacterStream(columnLabel, reader); + } + + /** + * Retrieves the value of the designated column in the current row of this ResultSet object + * as a java.net.URL object. + * + * @param columnIndex the index of the column from which the URL is to be retrieved, where + */ + @Override + public URL getURL(final int columnIndex) throws SQLException { + return resultSet.getURL(columnIndex); + } + + /** + * Retrieves the value of the designated column as a URL object. + * + * @param columnLabel the label for the column, which is the column name defined during table creation + * @return the column value as a URL object, or null if the SQL value is SQL NULL + * @throws SQLException if a database access error occurs or the columnLabel is not valid + */ + @Override + public URL getURL(final String columnLabel) throws SQLException { + return resultSet.getURL(columnLabel); + } + + /** + * Updates the designated column with a Ref value. + * The updater methods are used to update column values in the current row + * or the insert row. The new row value will be updated into the database + * when the method updateRow is called. + * + * @param columnIndex the first column is 1, the second is 2, and so on + * @param x the new column value; must be a Ref object + * @throws SQLException if a database access error occurs, if the result set + * concurrency is CONCUR_READ_ONLY, or if this method + * is called on a closed result set + */ + @Override + public void updateRef(final int columnIndex, final Ref x) throws SQLException { + resultSet.updateRef(columnIndex, x); + } + + /** + * Updates the designated column with a Ref value. + * This method should be called when updating a column in a ResultSet with a Ref object. + * + * @param columnLabel the label for the column specified in the query, used to identify the column being updated + * @param x the Ref object containing the value to update the column with + * @throws SQLException if a database access error occurs, the ResultSet is in a read-only mode, + * or if this method is called on a non-updatable ResultSet + */ + @Override + public void updateRef(final String columnLabel, final Ref x) throws SQLException { + resultSet.updateRef(columnLabel, x); + } + } diff --git a/core/src/main/java/de/neitzel/core/util/ArrayUtils.java b/core/src/main/java/de/neitzel/core/util/ArrayUtils.java index 0abb26d..1ff0bfd 100644 --- a/core/src/main/java/de/neitzel/core/util/ArrayUtils.java +++ b/core/src/main/java/de/neitzel/core/util/ArrayUtils.java @@ -13,7 +13,7 @@ public class ArrayUtils { * static utility methods for array-related operations. * * @throws UnsupportedOperationException always, to indicate that this class - * should not be instantiated. + * should not be instantiated. */ private ArrayUtils() { throw new UnsupportedOperationException("Utility class"); @@ -23,11 +23,11 @@ public class ArrayUtils { * Checks if the given character array contains the specified character. * * @param array the character array to be searched - * @param ch the character to search for in the array + * @param ch the character to search for in the array * @return true if the character is found in the array, false otherwise */ public static boolean contains(char[] array, char ch) { - for(int index=0; index < array.length; index++) { + for (int index = 0; index < array.length; index++) { if (array[index] == ch) return true; } return false; @@ -37,11 +37,11 @@ public class ArrayUtils { * Checks if the specified integer array contains the given integer value. * * @param array the array of integers to search - * @param ch the integer value to search for in the array + * @param ch the integer value to search for in the array * @return true if the array contains the specified integer value, false otherwise */ public static boolean contains(int[] array, int ch) { - for(int index=0; index < array.length; index++) { + for (int index = 0; index < array.length; index++) { if (array[index] == ch) return true; } return false; @@ -51,11 +51,11 @@ public class ArrayUtils { * Checks if the specified long array contains the given long value. * * @param array the array of long values to search - * @param ch the long value to search for in the array + * @param ch the long value to search for in the array * @return true if the array contains the specified long value, false otherwise */ public static boolean contains(long[] array, long ch) { - for(int index=0; index < array.length; index++) { + for (int index = 0; index < array.length; index++) { if (array[index] == ch) return true; } return false; @@ -65,12 +65,12 @@ public class ArrayUtils { * Checks if the specified array contains the given element. * * @param array the array to be searched - * @param ch the element to search for in the array - * @param the type of the elements in the array + * @param ch the element to search for in the array + * @param the type of the elements in the array * @return true if the element is found in the array, false otherwise */ public static boolean contains(T[] array, T ch) { - for(int index=0; index < array.length; index++) { + for (int index = 0; index < array.length; index++) { if (Objects.equals(array[index], ch)) return true; } return false; diff --git a/core/src/main/java/de/neitzel/core/util/EnumUtil.java b/core/src/main/java/de/neitzel/core/util/EnumUtil.java index 5b029d5..3ae7ba1 100644 --- a/core/src/main/java/de/neitzel/core/util/EnumUtil.java +++ b/core/src/main/java/de/neitzel/core/util/EnumUtil.java @@ -14,7 +14,7 @@ public class EnumUtil { * static utility methods for array-related operations. * * @throws UnsupportedOperationException always, to indicate that this class - * should not be instantiated. + * should not be instantiated. */ private EnumUtil() { throw new UnsupportedOperationException("Utility class"); @@ -25,7 +25,7 @@ public class EnumUtil { * of the enum constants within the specified Enum class. The pattern also includes optional delimiters * such as commas, spaces, and empty values, enabling the matching of lists or sequences of flag values. * - * @param The type of the Enum. + * @param The type of the Enum. * @param clazz The Enum class for which the regular expression is to be generated. * @return A String containing the regular expression pattern for matching the Enum's flag values. */ @@ -33,9 +33,9 @@ public class EnumUtil { StringBuilder result = new StringBuilder(); result.append("(|,|\\s"); - for (T flag: clazz.getEnumConstants()) { + for (T flag : clazz.getEnumConstants()) { result.append("|"); - for(char ch: flag.toString().toUpperCase().toCharArray()) { + for (char ch : flag.toString().toUpperCase().toCharArray()) { if (Character.isAlphabetic(ch)) { result.append("["); result.append(ch); @@ -52,25 +52,25 @@ public class EnumUtil { /** * Parses a delimited string containing Enum constant names into a list of Enum constants. - * + *

* This method takes an Enum class and a string of flags, splits the string by commas * or whitespace, and converts each substring into an Enum constant of the given class. * The flag names are case-insensitive and will be converted to uppercase before matching * to the Enum constants. * - * @param The type of the Enum. + * @param The type of the Enum. * @param clazz The Enum class to which the flags should be parsed. * @param flags A string containing the delimited list of flag names to parse. * Individual names can be separated by commas or whitespace. * @return A list of Enum constants parsed from the input string. If the input string - * is null or empty, an empty list is returned. + * is null or empty, an empty list is returned. * @throws IllegalArgumentException if any of the flag names do not match the constants in the given Enum class. - * @throws NullPointerException if the clazz parameter is null. + * @throws NullPointerException if the clazz parameter is null. */ public static > List parseFlags(final Class clazz, final String flags) { List result = new ArrayList<>(); if (flags != null) { - for (String flag: flags.split("[,\\s]")) { + for (String flag : flags.split("[,\\s]")) { if (!flag.isEmpty()) result.add(T.valueOf(clazz, flag.toUpperCase())); } } diff --git a/core/src/main/java/de/neitzel/core/util/RegionalizationMessage.java b/core/src/main/java/de/neitzel/core/util/RegionalizationMessage.java index 345ee10..bb697b9 100644 --- a/core/src/main/java/de/neitzel/core/util/RegionalizationMessage.java +++ b/core/src/main/java/de/neitzel/core/util/RegionalizationMessage.java @@ -16,7 +16,7 @@ public class RegionalizationMessage { * which is used to retrieve locale-specific objects and messages. * It facilitates the process of internationalization by loading resources * such as text and messages from specified bundles based on the provided locale. - * + *

* This variable is initialized in constructors of the `RegionalizationMessage` class * and is used internally by various methods to fetch localized messages. */ @@ -50,21 +50,36 @@ public class RegionalizationMessage { * * @param key The key for which the localized message needs to be retrieved. * @return The localized message as a String if the key exists in the resource bundle; - * otherwise, null. + * otherwise, null. */ public String getMessage(final String key) { if (!res.containsKey(key)) return null; return res.getString(key); } + /** + * Retrieves a localized and formatted message from a resource bundle based on a key. + * If the key is not found in the resource bundle, a default message is used. + * The message supports parameter substitution using the supplied arguments. + * + * @param key The key used to retrieve the localized message from the resource bundle. + * @param defaultMessage The default message to be used if the key is not found in the resource bundle. + * @param params The parameters to substitute into the message placeholders. + * @return A formatted string containing the localized message with substituted parameters. + */ + public String getFormattedMessage(final String key, final String defaultMessage, final Object... params) { + MessageFormat format = new MessageFormat(getMessage(key, defaultMessage)); + return format.format(params); + } + /** * Retrieves a localized message for the given key from the resource bundle. * If the key is not found, the specified default message is returned. * - * @param key The key to look up in the resource bundle. + * @param key The key to look up in the resource bundle. * @param defaultMessage The default message to return if the key is not found. * @return The localized message corresponding to the key, or the default message - * if the key does not exist in the resource bundle. + * if the key does not exist in the resource bundle. */ public String getMessage(final String key, final String defaultMessage) { if (res.containsKey(key)) @@ -72,19 +87,4 @@ public class RegionalizationMessage { return defaultMessage; } - - /** - * Retrieves a localized and formatted message from a resource bundle based on a key. - * If the key is not found in the resource bundle, a default message is used. - * The message supports parameter substitution using the supplied arguments. - * - * @param key The key used to retrieve the localized message from the resource bundle. - * @param defaultMessage The default message to be used if the key is not found in the resource bundle. - * @param params The parameters to substitute into the message placeholders. - * @return A formatted string containing the localized message with substituted parameters. - */ - public String getFormattedMessage(final String key, final String defaultMessage, final Object... params) { - MessageFormat format = new MessageFormat(getMessage(key, defaultMessage)); - return format.format(params); - } } diff --git a/core/src/main/java/de/neitzel/core/util/StopWatch.java b/core/src/main/java/de/neitzel/core/util/StopWatch.java index 406ffc4..856d6a4 100644 --- a/core/src/main/java/de/neitzel/core/util/StopWatch.java +++ b/core/src/main/java/de/neitzel/core/util/StopWatch.java @@ -7,122 +7,140 @@ import java.util.Locale; /** * A utility class for measuring elapsed time. The StopWatch can be started, stopped, and queried for the elapsed time in various formats. */ +@SuppressWarnings("unused") public class StopWatch { - /** - * Represents the starting time of the stopwatch. This variable is set when the stopwatch is started and is used to calculate the elapsed - * duration between the start and the stop or the current time. - */ - private Instant startTime; - /** - * Represents the stopping time of the stopwatch. This variable is set when the stopwatch is stopped and is used to calculate the elapsed - * duration between the start and stop times. - */ - private Instant stopTime; + /** + * Represents the starting time of the stopwatch. This variable is set when the stopwatch is started and is used to calculate the elapsed + * duration between the start and the stop or the current time. + */ + private Instant startTime; - /** - * Starts the stopwatch by recording the current time as the starting time. If the stopwatch was previously stopped or not yet started, - * this method resets the starting time to the current time and clears the stopping time. This method is typically called before measuring - * elapsed time. - */ - public void start() { - this.startTime = Instant.now(); - this.stopTime = null; - } + /** + * Represents the stopping time of the stopwatch. This variable is set when the stopwatch is stopped and is used to calculate the elapsed + * duration between the start and stop times. + */ + private Instant stopTime; - /** - * Stops the stopwatch by recording the current time as the stopping time. - *

- * This method should only be called after the stopwatch has been started using the {@code start()} method. If the stopwatch has not been - * started, an {@code IllegalStateException} will be thrown. Once this method is called, the elapsed time can be calculated as the - * duration between the starting and stopping times. - * - * @throws IllegalStateException if the stopwatch has not been started prior to calling this method. - */ - public void stop() { - if (startTime == null) { - throw new IllegalStateException("StopWatch must be started before stopping."); - } - this.stopTime = Instant.now(); - } - - /** - * Calculates the amount of time elapsed between the stopwatch's starting time and either its stopping time or the current time if the - * stopwatch is still running. - * - * @return the duration representing the elapsed time between the start and end points of the stopwatch. - * @throws IllegalStateException if the stopwatch has not been started before calling this method. - */ - public Duration getUsedTime() { - if (startTime == null) { - throw new IllegalStateException("StopWatch has not been started."); - } - Instant end = (stopTime != null) ? stopTime : Instant.now(); - return Duration.between(startTime, end); - } - - /** - * Formats the duration of elapsed time measured by the stopwatch into a human-readable string. The formatted output may include days, - * hours, minutes, seconds, and milliseconds, depending on the parameters. The method retrieves the elapsed time via the - * {@code getUsedTime} method and formats it based on the specified flags. - * - * @param includeMillis whether to include milliseconds in the formatted output - * @param includeSeconds whether to include seconds in the formatted output - * @param includeMinutes whether to include minutes in the formatted output - * @param includeHours whether to include hours in the formatted output - * @param includeDays whether to include days in the formatted output - * @return a formatted string representing the elapsed time, including the components specified by the parameters - */ - public String getUsedTimeFormatted(boolean includeMillis, boolean includeSeconds, boolean includeMinutes, boolean includeHours, - boolean includeDays) { - Duration duration = getUsedTime(); - - long millis = duration.toMillis(); - long days = millis / (24 * 60 * 60 * 1000); - millis %= (24 * 60 * 60 * 1000); - - long hours = millis / (60 * 60 * 1000); - millis %= (60 * 60 * 1000); - long minutes = millis / (60 * 1000); - millis %= (60 * 1000); - long seconds = millis / 1000; - millis %= 1000; - - StringBuilder sb = new StringBuilder(); - - if (includeDays && days > 0) { - sb.append(days).append("d "); - } - if (includeHours && (hours > 0 || sb.length() > 0)) { - sb.append(hours).append("h "); - } - if (includeMinutes && (minutes > 0 || sb.length() > 0)) { - sb.append(minutes).append("m "); - } - if (includeSeconds && (seconds > 0 || sb.length() > 0)) { - sb.append(seconds); - } - if (includeMillis) { - if (includeSeconds) { - sb.append(String.format(Locale.US, ".%03d", millis)); - } else { - sb.append(millis).append("ms"); - } + /** + * Creates a new StopWatch instance in the reset state. + * + *

The constructor does not start timing. Both {@link #startTime} and {@link #stopTime} + * are initialized to {@code null}. To begin measuring elapsed time, call {@link #start()}. + * After calling {@link #stop()}, retrieve the measured duration with {@link #getUsedTime()} or + * a human-readable string via {@link #getUsedTimeFormatted(boolean, boolean, boolean, boolean, boolean)}. + *

+ * + *

Note: This class is not synchronized; synchronize externally if the same instance + * is accessed from multiple threads.

+ */ + public StopWatch() { + // default constructor only ... } - String result = sb.toString().trim(); - return result.isEmpty() ? "0ms" : result; - } + /** + * Starts the stopwatch by recording the current time as the starting time. If the stopwatch was previously stopped or not yet started, + * this method resets the starting time to the current time and clears the stopping time. This method is typically called before measuring + * elapsed time. + */ + public void start() { + this.startTime = Instant.now(); + this.stopTime = null; + } - /** - * Provides a compact and human-readable formatted string representing the elapsed time measured by the stopwatch. The method formats the - * duration using a combination of days, hours, minutes, seconds, and milliseconds. This compact format removes additional verbosity in - * favor of a shorter, more concise representation. - * - * @return a compact formatted string representing the elapsed time, including days, hours, minutes, seconds, and milliseconds as - * applicable - */ - public String getUsedTimeFormattedCompact() { - return getUsedTimeFormatted(true, true, true, true, true); - } + /** + * Stops the stopwatch by recording the current time as the stopping time. + *

+ * This method should only be called after the stopwatch has been started using the {@code start()} method. If the stopwatch has not been + * started, an {@code IllegalStateException} will be thrown. Once this method is called, the elapsed time can be calculated as the + * duration between the starting and stopping times. + * + * @throws IllegalStateException if the stopwatch has not been started prior to calling this method. + */ + public void stop() { + if (startTime == null) { + throw new IllegalStateException("StopWatch must be started before stopping."); + } + this.stopTime = Instant.now(); + } + + /** + * Provides a compact and human-readable formatted string representing the elapsed time measured by the stopwatch. The method formats the + * duration using a combination of days, hours, minutes, seconds, and milliseconds. This compact format removes additional verbosity in + * favor of a shorter, more concise representation. + * + * @return a compact formatted string representing the elapsed time, including days, hours, minutes, seconds, and milliseconds as + * applicable + */ + public String getUsedTimeFormattedCompact() { + return getUsedTimeFormatted(true, true, true, true, true); + } + + /** + * Formats the duration of elapsed time measured by the stopwatch into a human-readable string. The formatted output may include days, + * hours, minutes, seconds, and milliseconds, depending on the parameters. The method retrieves the elapsed time via the + * {@code getUsedTime} method and formats it based on the specified flags. + * + * @param includeMillis whether to include milliseconds in the formatted output + * @param includeSeconds whether to include seconds in the formatted output + * @param includeMinutes whether to include minutes in the formatted output + * @param includeHours whether to include hours in the formatted output + * @param includeDays whether to include days in the formatted output + * @return a formatted string representing the elapsed time, including the components specified by the parameters + */ + public String getUsedTimeFormatted(boolean includeMillis, boolean includeSeconds, boolean includeMinutes, boolean includeHours, + boolean includeDays) { + Duration duration = getUsedTime(); + + long millis = duration.toMillis(); + long days = millis / (24 * 60 * 60 * 1000); + millis %= (24 * 60 * 60 * 1000); + + long hours = millis / (60 * 60 * 1000); + millis %= (60 * 60 * 1000); + long minutes = millis / (60 * 1000); + millis %= (60 * 1000); + long seconds = millis / 1000; + millis %= 1000; + + StringBuilder sb = new StringBuilder(); + + if (includeDays && days > 0) { + sb.append(days).append("d "); + } + if (includeHours && (hours > 0 || !sb.isEmpty())) { + sb.append(hours).append("h "); + } + if (includeMinutes && (minutes > 0 || !sb.isEmpty())) { + sb.append(minutes).append("m "); + } + if (includeSeconds && (seconds > 0 || !sb.isEmpty())) { + sb.append(seconds); + } + if (includeMillis) { + if (includeSeconds) { + sb.append(String.format(Locale.US, ".%03d", millis)); + } else { + sb.append(millis).append("ms"); + } + } + + String result = sb.toString().trim(); + return result.isEmpty() ? "0ms" : result; + } + + /** + * Calculates the amount of time elapsed between the stopwatch's starting time and either its stopping time or the current time if the + * stopwatch is still running. + * + * @return the duration representing the elapsed time between the start and end points of the stopwatch. + * @throws IllegalStateException if the stopwatch has not been started before calling this method. + */ + public Duration getUsedTime() { + if (startTime == null) { + throw new IllegalStateException("StopWatch has not been started."); + } + Instant end = (stopTime != null) ? stopTime : Instant.now(); + return Duration.between(startTime, end); + } } diff --git a/core/src/main/java/de/neitzel/core/util/Strings.java b/core/src/main/java/de/neitzel/core/util/Strings.java index 6034981..6b43bc1 100644 --- a/core/src/main/java/de/neitzel/core/util/Strings.java +++ b/core/src/main/java/de/neitzel/core/util/Strings.java @@ -8,33 +8,33 @@ import java.util.Map; * Utility class providing common string manipulation methods. */ public class Strings { + /** + * A map that holds the system's environment variables. The keys represent + * environment variable names, and the values represent their corresponding + * values. It is initialized with the current system environment variables using + * {@link System#getenv()}. + *

+ * This variable provides access to the underlying system environment, which can + * be used for various purposes such as configuration, path resolution, or + * dynamic value substitution. + *

+ * Note: Modifications to this map will not affect the system environment, as it + * is a copy of the environment at the time of initialization. + */ + private static Map environmentVariables = System.getenv(); + /** * Private constructor to prevent instantiation of the utility class. * This utility class is not meant to be instantiated, as it only provides * static utility methods for array-related operations. * * @throws UnsupportedOperationException always, to indicate that this class - * should not be instantiated. + * should not be instantiated. */ private Strings() { throw new UnsupportedOperationException("Utility class"); } - /** - * A map that holds the system's environment variables. The keys represent - * environment variable names, and the values represent their corresponding - * values. It is initialized with the current system environment variables using - * {@link System#getenv()}. - * - * This variable provides access to the underlying system environment, which can - * be used for various purposes such as configuration, path resolution, or - * dynamic value substitution. - * - * Note: Modifications to this map will not affect the system environment, as it - * is a copy of the environment at the time of initialization. - */ - private static Map environmentVariables = System.getenv(); - /** * Expands environment variable placeholders within the provided text. * Placeholders in the format ${VARIABLE_NAME} are replaced with their @@ -43,8 +43,8 @@ public class Strings { * @param text The input string containing environment variable placeholders. * If null, the method returns null. * @return A string with the placeholders replaced by their corresponding - * environment variable values. If no placeholders are found, - * the original string is returned. + * environment variable values. If no placeholders are found, + * the original string is returned. */ public static String expandEnvironmentVariables(String text) { if (text == null) return null; @@ -63,7 +63,7 @@ public class Strings { * @return true if the string is null or has a length of 0; false otherwise. */ public static boolean isNullOrEmpty(final String string) { - return (string == null || string.length()==0); + return (string == null || string.length() == 0); } /** @@ -73,12 +73,12 @@ public class Strings { * @param value The input string that might contain surrounding double quotes. * The input cannot be null, and leading/trailing whitespaces will be ignored. * @return A string with leading and trailing double quotes removed if present. - * Returns the original string if no surrounding double quotes are detected. + * Returns the original string if no surrounding double quotes are detected. */ public static String removeQuotes(final String value) { String trimmedValue = value.trim(); if (trimmedValue.length() > 1 && trimmedValue.startsWith("\"") && trimmedValue.endsWith("\"")) - return trimmedValue.substring(1, trimmedValue.length()-1); + return trimmedValue.substring(1, trimmedValue.length() - 1); return value; } @@ -87,11 +87,11 @@ public class Strings { * Replaces illegal characters in a given string with a specified replacement string. * Optionally, consecutive illegal characters can be combined into a single replacement. * - * @param value The input string in which illegal characters are to be replaced. + * @param value The input string in which illegal characters are to be replaced. * @param illegalCharacters A string specifying the set of illegal characters to be matched. - * @param replacement The string to replace each illegal character or group of characters. - * @param combine A boolean flag indicating whether consecutive illegal characters should be replaced - * with a single replacement string. If true, groups of illegal characters are combined. + * @param replacement The string to replace each illegal character or group of characters. + * @param combine A boolean flag indicating whether consecutive illegal characters should be replaced + * with a single replacement string. If true, groups of illegal characters are combined. * @return A new string with the illegal characters replaced by the provided replacement string. */ public static String replaceIllegalCharacters(final String value, final String illegalCharacters, final String replacement, final boolean combine) { @@ -104,12 +104,12 @@ public class Strings { * with a specified replacement string. Optionally combines consecutive non-allowed * characters into a single replacement. * - * @param value The input string to be processed. + * @param value The input string to be processed. * @param allowedCharacters A string containing the set of characters that are allowed. - * Any character not in this set will be replaced. - * @param replacement The string to replace non-allowed characters with. - * @param combine If true, consecutive non-allowed characters will be replaced with - * a single instance of the replacement string. + * Any character not in this set will be replaced. + * @param replacement The string to replace non-allowed characters with. + * @param combine If true, consecutive non-allowed characters will be replaced with + * a single instance of the replacement string. * @return A new string with non-allowed characters replaced according to the specified rules. */ public static String replaceNonAllowedCharacters(final String value, final String allowedCharacters, final String replacement, final boolean combine) { @@ -131,11 +131,11 @@ public class Strings { public static String increment(@NonNull final String element) { if (element.isEmpty()) return "1"; - String firstPart = element.substring(0, element.length()-1); - char lastChar = element.charAt(element.length()-1); + String firstPart = element.substring(0, element.length() - 1); + char lastChar = element.charAt(element.length() - 1); if (lastChar == '9') return firstPart + 'A'; if (lastChar == 'Z') return increment(firstPart) + '0'; - return firstPart + (char)(lastChar+1); + return firstPart + (char) (lastChar + 1); } /** @@ -144,10 +144,10 @@ public class Strings { * the string is returned unchanged. If the input string's length exceeds the max * length, it is truncated to that length. * - * @param original The original input string to be processed. If null, the method returns null. + * @param original The original input string to be processed. If null, the method returns null. * @param maxLength The maximum number of characters allowed in the resulting string. * @return The original string if its length is less than or equal to maxLength, - * otherwise a truncated version of the string up to maxLength characters. + * otherwise a truncated version of the string up to maxLength characters. */ public static String limitCharNumber(final String original, final int maxLength) { if (original == null || original.length() <= maxLength) return original; diff --git a/core/src/main/java/de/neitzel/core/util/XmlUtils.java b/core/src/main/java/de/neitzel/core/util/XmlUtils.java index 61a96a9..f8cc120 100644 --- a/core/src/main/java/de/neitzel/core/util/XmlUtils.java +++ b/core/src/main/java/de/neitzel/core/util/XmlUtils.java @@ -8,7 +8,12 @@ import org.w3c.dom.Node; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.*; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; @@ -25,214 +30,211 @@ import java.util.Date; */ @Slf4j public class XmlUtils { - /** - * Private constructor to prevent instantiation of the utility class. - * This utility class is not meant to be instantiated, as it only provides - * static utility methods for array-related operations. - * - * @throws UnsupportedOperationException always, to indicate that this class - * should not be instantiated. - */ - private XmlUtils() { - throw new UnsupportedOperationException("Utility class"); - } + /** + * A {@link DateTimeFormatter} instance used for formatting or parsing dates in the "yyyy-MM-dd" pattern. + *

+ * This formatter adheres to the XML date format standard (ISO-8601). It can be used + * to ensure consistent date representations in XML or other similar text-based formats. + *

+ * Thread-safe and immutable, this formatter can be shared across multiple threads. + */ + public static final DateTimeFormatter XML_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - /** - * A {@link DateTimeFormatter} instance used for formatting or parsing dates in the "yyyy-MM-dd" pattern. - * - * This formatter adheres to the XML date format standard (ISO-8601). It can be used - * to ensure consistent date representations in XML or other similar text-based formats. - * - * Thread-safe and immutable, this formatter can be shared across multiple threads. - */ - public static final DateTimeFormatter XML_DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + /** + * Private constructor to prevent instantiation of the utility class. + * This utility class is not meant to be instantiated, as it only provides + * static utility methods for array-related operations. + * + * @throws UnsupportedOperationException always, to indicate that this class + * should not be instantiated. + */ + private XmlUtils() { + throw new UnsupportedOperationException("Utility class"); + } - /** - * Creates a new element in the provided XML document with the specified name. - * - * @param doc The XML document in which the new element is to be created. Must not be null. - * @param name The name of the element to be created. Must not be null or empty. - * @return The newly created element with the given name. Never returns null. - */ - public static Element createElement(final Document doc, final String name) { - log.debug("Creating a new element " + name); - return doc.createElement(name); - } + /** + * Creates an XML element with the specified name and value, formatted as a date string. + * The date value is converted to an XML-compatible string format using a predefined formatter. + * + * @param doc the XML document to which the element belongs; must not be null + * @param name the name of the element to be created; must not be null or empty + * @param value the date value to be assigned to the created element; must not be null + * @return the created XML element containing the specified name and formatted date value + */ + public static Element createElement(final Document doc, final String name, final Date value) { + return createElement(doc, name, XML_DATE_FORMATTER.format(value.toInstant())); + } - /** - * Creates a new XML element with the specified name and value, appends the value - * as a text node to the element, and returns the resulting element. - * - * @param doc the XML document to which the element belongs. Must not be null. - * @param name the name of the element to create. Must not be null. - * @param value the text value to be set as the content of the created element. - * If null, an empty string will be used as the content. - * @return the newly created XML element containing the specified value as a text node. - */ - public static Element createElement(final Document doc, final String name, final String value) { - log.debug("Creating a new element " + name + " with value: " + value); - Element element = doc.createElement(name); + /** + * Creates a new XML element with the specified name and value, appends the value + * as a text node to the element, and returns the resulting element. + * + * @param doc the XML document to which the element belongs. Must not be null. + * @param name the name of the element to create. Must not be null. + * @param value the text value to be set as the content of the created element. + * If null, an empty string will be used as the content. + * @return the newly created XML element containing the specified value as a text node. + */ + public static Element createElement(final Document doc, final String name, final String value) { + log.debug("Creating a new element " + name + " with value: " + value); + Element element = doc.createElement(name); - Node content = doc.createTextNode(value != null ? value : ""); - element.appendChild(content); + Node content = doc.createTextNode(value != null ? value : ""); + element.appendChild(content); - return element; - } + return element; + } - /** - * Creates an XML element with the specified name and value, formatted as a date string. - * The date value is converted to an XML-compatible string format using a predefined formatter. - * - * @param doc the XML document to which the element belongs; must not be null - * @param name the name of the element to be created; must not be null or empty - * @param value the date value to be assigned to the created element; must not be null - * @return the created XML element containing the specified name and formatted date value - */ - public static Element createElement(final Document doc, final String name, final Date value) { - return createElement(doc, name, XML_DATE_FORMATTER.format(value.toInstant())); - } + /** + * Creates an XML element with the specified name and optional value. + * + * @param doc The Document object to which the element will belong. Must not be null. + * @param name The name of the element to be created. Must not be null or empty. + * @param value The optional value to be set as the text content of the element. If null, + * the element will have an empty text content. + * @return The newly created Element object with the specified name and value. + */ + public static Element createElement(final Document doc, final String name, final Integer value) { + log.debug("Creating a new element " + name + " with value: " + value); + Element element = doc.createElement(name); - /** - * Creates an XML element with the specified name and optional value. - * - * @param doc The Document object to which the element will belong. Must not be null. - * @param name The name of the element to be created. Must not be null or empty. - * @param value The optional value to be set as the text content of the element. If null, - * the element will have an empty text content. - * @return The newly created Element object with the specified name and value. - */ - public static Element createElement(final Document doc, final String name, final Integer value) { - log.debug("Creating a new element " + name + " with value: " + value); - Element element = doc.createElement(name); + Node content = doc.createTextNode(value != null ? "" + value : ""); + element.appendChild(content); - Node content = doc.createTextNode(value != null ? ""+value : ""); - element.appendChild(content); + return element; + } - return element; - } + /** + * Creates a new element with the specified name, appends it to the provided parent element, + * and returns the newly created element. + * + * @param doc The Document to which the new element belongs. Must not be null. + * @param name The name of the new element to be created. Must not be null or empty. + * @param parent The parent element to which the new element will be appended. Must not be null. + * @return The newly created and appended Element object. + */ + public static Element createAndInsertElement(final Document doc, final String name, @NonNull final Element parent) { + log.debug("Creating a new element " + name + " and adding it to a parent."); + Element element = createElement(doc, name); + parent.appendChild(element); + return element; + } - /** - * Creates a new element with the specified name, appends it to the provided parent element, - * and returns the newly created element. - * - * @param doc The Document to which the new element belongs. Must not be null. - * @param name The name of the new element to be created. Must not be null or empty. - * @param parent The parent element to which the new element will be appended. Must not be null. - * @return The newly created and appended Element object. - */ - public static Element createAndInsertElement(final Document doc, final String name, @NonNull final Element parent) { - log.debug("Creating a new element " + name + " and adding it to a parent."); - Element element = createElement(doc, name); - parent.appendChild(element); - return element; - } + /** + * Creates a new element in the provided XML document with the specified name. + * + * @param doc The XML document in which the new element is to be created. Must not be null. + * @param name The name of the element to be created. Must not be null or empty. + * @return The newly created element with the given name. Never returns null. + */ + public static Element createElement(final Document doc, final String name) { + log.debug("Creating a new element " + name); + return doc.createElement(name); + } - /** - * Creates a new XML element with a specified name and value, adds it to the specified parent element, - * and returns the created element. - * - * @param doc The XML document to which the new element belongs. Must not be null. - * @param name The name of the element to create. Must not be null. - * @param value The value to be set for the created element. Can be null if no value is required. - * @param parent The parent element to which the new element will be appended. Must not be null. - * @return The newly created and inserted element. - */ - public static Element createAndInsertElement(final Document doc, final String name, final String value, @NonNull final Element parent) { - log.debug("Creating a new element " + name + " with value: " + value + " and adding it to a parent."); - Element element = createElement(doc, name, value); - parent.appendChild(element); - return element; - } + /** + * Creates a new XML element with a specified name and value, adds it to the specified parent element, + * and returns the created element. + * + * @param doc The XML document to which the new element belongs. Must not be null. + * @param name The name of the element to create. Must not be null. + * @param value The value to be set for the created element. Can be null if no value is required. + * @param parent The parent element to which the new element will be appended. Must not be null. + * @return The newly created and inserted element. + */ + public static Element createAndInsertElement(final Document doc, final String name, final String value, @NonNull final Element parent) { + log.debug("Creating a new element " + name + " with value: " + value + " and adding it to a parent."); + Element element = createElement(doc, name, value); + parent.appendChild(element); + return element; + } + /** + * Formats a given XML string by applying proper indentation to enhance readability. + * The method uses a transformer to process the XML input, applying indentation + * with a four-space configuration. In case of an error, the original XML string + * is returned without any modifications. + * + * @param xmlStream The raw XML string to be formatted. Cannot be null. + * @return The formatted XML string with proper indentation. If an exception occurs + * during formatting, the original XML string is returned. + */ + public static String format(final String xmlStream) { + log.debug("formatXML"); - /** - * Formats a given XML string by applying proper indentation to enhance readability. - * The method uses a transformer to process the XML input, applying indentation - * with a four-space configuration. In case of an error, the original XML string - * is returned without any modifications. - * - * @param xmlStream The raw XML string to be formatted. Cannot be null. - * @return The formatted XML string with proper indentation. If an exception occurs - * during formatting, the original XML string is returned. - */ - public static String format(final String xmlStream) { - log.debug("formatXML"); + try { + Source xmlInput = new StreamSource(new StringReader(xmlStream)); + StringWriter stringWriter = new StringWriter(); + StreamResult xmlOutput = new StreamResult(stringWriter); - try { - Source xmlInput = new StreamSource(new StringReader(xmlStream)); - StringWriter stringWriter = new StringWriter(); - StreamResult xmlOutput = new StreamResult(stringWriter); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + transformerFactory.setAttribute("indent-number", "4"); - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - transformerFactory.setAttribute("indent-number", "4"); + Transformer transformer = transformerFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.transform(xmlInput, xmlOutput); - Transformer transformer = transformerFactory.newTransformer(); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.transform(xmlInput, xmlOutput); + return xmlOutput.getWriter().toString(); + } catch (TransformerException e) { + log.error("Error in XML: " + e.getMessage() + "\n" + xmlStream, e); + } - return xmlOutput.getWriter().toString(); - } - catch(TransformerException e) { - log.error("Error in XML: " + e.getMessage() + "\n"+xmlStream, e); - } + return xmlStream; + } - return xmlStream; - } + /** + * Formats a given XML Document into a human-readable string representation. + * The method applies indentation and specific output properties to the XML content. + * If an exception occurs during the transformation process, it logs the error + * and returns null. + * + * @param doc The XML Document to be formatted. Must not be null. + * @return A formatted string representation of the XML document, or null if an error occurs during processing. + */ + public static String format(final Document doc) { + try { + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + transformerFactory.setAttribute("indent-number", "4"); + Transformer transformer = transformerFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.STANDALONE, "yes"); + transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1"); + StringWriter stringWriter = new StringWriter(); - /** - * Formats a given XML Document into a human-readable string representation. - * The method applies indentation and specific output properties to the XML content. - * If an exception occurs during the transformation process, it logs the error - * and returns null. - * - * @param doc The XML Document to be formatted. Must not be null. - * @return A formatted string representation of the XML document, or null if an error occurs during processing. - */ - public static String format(final Document doc) { - try { - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - transformerFactory.setAttribute("indent-number", "4"); - Transformer transformer = transformerFactory.newTransformer(); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty(OutputKeys.STANDALONE, "yes"); - transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1"); - StringWriter stringWriter = new StringWriter(); + Source source = new DOMSource(doc); + Result result = new StreamResult(stringWriter); + transformer.transform(source, result); - Source source = new DOMSource(doc); - Result result = new StreamResult(stringWriter); - transformer.transform(source, result); + String xmlString = stringWriter.toString(); + log.info("MO Request: " + xmlString); + return xmlString; + } catch (TransformerException e) { + log.error("Error in XML Transformation: " + e.getMessage(), e); + } - String xmlString = stringWriter.toString(); - log.info("MO Request: " + xmlString); - return xmlString; - } - catch(TransformerException e) { - log.error("Error in XML Transformation: " + e.getMessage(), e); - } + return null; + } - return null; - } - - /** - * Validates whether a given XML string is well-formed. - * This method attempts to parse the input XML string and checks - * if it can successfully create a valid DOM object from it. - * - * @param xml The XML string to be validated. Must not be null. - * If null or invalid, the method will return false. - * @return true if the XML string is well-formed and can be successfully parsed; - * false otherwise, such as in the case of invalid content or parsing errors. - */ - public static boolean checkXml(final String xml) { - try { - InputStream stream = new ByteArrayInputStream(xml.getBytes()); - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder = dbf.newDocumentBuilder(); - Document document = docBuilder.parse(stream); - return document != null; - } catch (Exception ex) { - log.warn("Exception when validating xml.", ex); - return false; - } - } + /** + * Validates whether a given XML string is well-formed. + * This method attempts to parse the input XML string and checks + * if it can successfully create a valid DOM object from it. + * + * @param xml The XML string to be validated. Must not be null. + * If null or invalid, the method will return false. + * @return true if the XML string is well-formed and can be successfully parsed; + * false otherwise, such as in the case of invalid content or parsing errors. + */ + public static boolean checkXml(final String xml) { + try { + InputStream stream = new ByteArrayInputStream(xml.getBytes()); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = dbf.newDocumentBuilder(); + Document document = docBuilder.parse(stream); + return document != null; + } catch (Exception ex) { + log.warn("Exception when validating xml.", ex); + return false; + } + } } diff --git a/core/src/test/java/de/neitzel/core/inject/InjectableComponentScannerTest.java b/core/src/test/java/de/neitzel/core/inject/InjectableComponentScannerTest.java index 2f7e140..075857d 100644 --- a/core/src/test/java/de/neitzel/core/inject/InjectableComponentScannerTest.java +++ b/core/src/test/java/de/neitzel/core/inject/InjectableComponentScannerTest.java @@ -7,7 +7,11 @@ import de.neitzel.core.inject.testcomponents.test1ok.TestInterface1_2; import de.neitzel.core.inject.testcomponents.test1ok.sub.TestComponent1_2; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; class InjectableComponentScannerTest { diff --git a/encryption/pom.xml b/encryption/pom.xml index d118b35..3474820 100644 --- a/encryption/pom.xml +++ b/encryption/pom.xml @@ -1,6 +1,6 @@ - 4.0.0 diff --git a/encryption/src/main/java/de/neitzel/encryption/BaseAlphabet.java b/encryption/src/main/java/de/neitzel/encryption/BaseAlphabet.java index 78bc4be..986da67 100644 --- a/encryption/src/main/java/de/neitzel/encryption/BaseAlphabet.java +++ b/encryption/src/main/java/de/neitzel/encryption/BaseAlphabet.java @@ -2,20 +2,26 @@ package de.neitzel.encryption; import com.idealista.fpe.config.Alphabet; -public abstract class BaseAlphabet implements Alphabet { +/** + * Base implementation of the {@link Alphabet} interface providing common helper methods + * for working with character sets and validating characters against the alphabet. + */ +public interface BaseAlphabet extends Alphabet { /** - * Replaces illegal characters of a string with a given replacement character - * @param text Text to check. - * @param replacement Replacement character. - * @return String in which all characters was replaced. + * Replaces illegal characters of a string with a given replacement character. + * + * @param text Text to check; may not be null + * @param replacement Replacement character to use for characters not present in the alphabet + * @return a new string in which every invalid character was replaced with the provided replacement + * @throws IllegalArgumentException if {@code replacement} is not a valid character in the alphabet */ - public String replaceIllegalCharacters(String text, char replacement) { + default String replaceIllegalCharacters(String text, char replacement) { // Validate if (!isValidCharacter(replacement)) throw new IllegalArgumentException("replacement"); StringBuilder result = new StringBuilder(); - for (char ch: text.toCharArray()) { - if (isValidCharacter(ch)){ + for (char ch : text.toCharArray()) { + if (isValidCharacter(ch)) { result.append(ch); } else { result.append(replacement); @@ -26,10 +32,11 @@ public abstract class BaseAlphabet implements Alphabet { /** * Checks if a given Character is part of the alphabet. + * * @param character Character to check. * @return true if character is valid, else false. */ - public boolean isValidCharacter(char character) { + default boolean isValidCharacter(char character) { // Compare with all characters for (char ch : availableCharacters()) { if (ch == character) return true; diff --git a/encryption/src/main/java/de/neitzel/encryption/FF1Encryption.java b/encryption/src/main/java/de/neitzel/encryption/FF1Encryption.java index 0134e2c..87c849d 100644 --- a/encryption/src/main/java/de/neitzel/encryption/FF1Encryption.java +++ b/encryption/src/main/java/de/neitzel/encryption/FF1Encryption.java @@ -7,49 +7,53 @@ import com.idealista.fpe.config.LengthRange; import javax.crypto.KeyGenerator; import java.security.NoSuchAlgorithmException; -import java.util.Random; +import java.security.SecureRandom; /** * Helper class to deal with FF1Encryption using com.idealista:format-preserving-encryption:1.0.0. */ +@SuppressWarnings("unused") public class FF1Encryption { - /** - * Key to use for all encryption / unencryption - */ - private byte[] key; + private static final SecureRandom RANDOM = new SecureRandom(); /** - * Should to small strings be ignored? - * - * If this is set to true, small strings (less than 2 characters) will not be encrypted! + * Key to use for all encryption / unencryption. */ - private boolean ignoreToShortStrings; + private final byte[] key; /** - * tweak to use for encryption + * Should too small strings be ignored? + * If this is set to true, small strings (less than {@code minLength} characters) + * will not be encrypted or decrypted and will be returned unchanged. */ - private byte[] tweak; + private final boolean ignoreToShortStrings; /** - * Domain used for encryption + * Tweak to use for encryption. */ - private Domain domain; + private final byte[] tweak; /** - * Format preserving encryption to use. + * Domain used for encryption. */ - private FormatPreservingEncryption encryption; + private final Domain domain; /** - * Minimum length of a string. + * Format preserving encryption implementation to use. */ - private int minLength; + private final FormatPreservingEncryption encryption; + + /** + * Minimum length of a string for which encryption/decryption will be applied. + */ + private final int minLength; /** * Creates a new instance of FF1Encryption - * @param key AES key to use. - * @param tweak tweak to use for encryption / decryption + * + * @param key AES key to use. + * @param tweak tweak to use for encryption / decryption * @param ignoreToShortStrings Ignore strings that are to short. */ public FF1Encryption(byte[] key, byte[] tweak, boolean ignoreToShortStrings) { @@ -58,12 +62,13 @@ public class FF1Encryption { /** * Creates a new instance of FF1Encryption - * @param key AES key to use. - * @param tweak tweak to use for encryption / decryption + * + * @param key AES key to use. + * @param tweak tweak to use for encryption / decryption * @param ignoreToShortStrings Ignore strings that are to short. - * @param domain Domain to use for encryption - * @param minLength Minimum length of string. - * @param maxLength Maximum length of string. + * @param domain Domain to use for encryption + * @param minLength Minimum length of string. + * @param maxLength Maximum length of string. */ public FF1Encryption(byte[] key, byte[] tweak, boolean ignoreToShortStrings, Domain domain, int minLength, int maxLength) { this.key = key; @@ -72,15 +77,45 @@ public class FF1Encryption { this.domain = domain; this.minLength = minLength; - encryption = FormatPreservingEncryptionBuilder - .ff1Implementation().withDomain(domain) + this.encryption = FormatPreservingEncryptionBuilder + .ff1Implementation() + .withDomain(domain) .withDefaultPseudoRandomFunction(key) .withLengthRange(new LengthRange(minLength, maxLength)) .build(); } + /** + * Creates a new AES key woth the given length. + * + * @param length Length of the key in bits. Must be 128, 192 or 256 bits + * @return Byte array of the new key. + */ + public static byte[] createNewKey(int length) { + try { + KeyGenerator keyGen = KeyGenerator.getInstance("AES"); + keyGen.init(length); // for example + return keyGen.generateKey().getEncoded(); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + } + + /** + * Creates a new tweak of the given length. + * + * @param length Number of bytes the new teeak should have. + * @return byte array with the new tweak. + */ + public static byte[] createNewTweak(int length) { + byte[] key = new byte[length]; + RANDOM.nextBytes(key); + return key; + } + /** * Encrypts a given text. + * * @param plainText Unencrypted text. * @return Encrypted text. */ @@ -97,6 +132,7 @@ public class FF1Encryption { /** * Decrypt a given text. + * * @param cipherText Encrypted text. * @return Decrypted text. */ @@ -110,31 +146,4 @@ public class FF1Encryption { // Return decrypted text. return encryption.decrypt(cipherText, tweak); } - - /** - * Creates a new AES key woth the given length. - * @param length Length of the key in bits. Must be 128, 192 or 256 bits - * @return Byte array of the new key. - */ - public static byte[] createNewKey(int length) { - try { - KeyGenerator keyGen = KeyGenerator.getInstance("AES"); - keyGen.init(length); // for example - return keyGen.generateKey().getEncoded(); - } catch (NoSuchAlgorithmException ex) { - throw new RuntimeException(ex); - } - } - - /** - * Creates a new tweak of the given length. - * @param length Number of bytes the new teeak should have. - * @return byte array with the new tweak. - */ - public static byte[] createNewTweak(int length) { - Random random = new Random(); - byte[] key = new byte[length]; - random.nextBytes(key); - return key; - } } diff --git a/encryption/src/main/java/de/neitzel/encryption/MainAlphabet.java b/encryption/src/main/java/de/neitzel/encryption/MainAlphabet.java index 10bd97d..f7cb308 100644 --- a/encryption/src/main/java/de/neitzel/encryption/MainAlphabet.java +++ b/encryption/src/main/java/de/neitzel/encryption/MainAlphabet.java @@ -3,12 +3,14 @@ package de.neitzel.encryption; /** * Main characters of the Alphabet. */ -public class MainAlphabet extends BaseAlphabet { +public class MainAlphabet implements BaseAlphabet { /** - * All characters we want to use. + * All characters that are part of the alphabet used by the MainDomain. + * This array includes lowercase letters, uppercase letters, digits, a set of + * special characters, and German-specific characters. */ - private static final char[] ALL_CHARS = new char[] { + private static final char[] ALL_CHARS = new char[]{ // lowercase characters 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', @@ -21,16 +23,38 @@ public class MainAlphabet extends BaseAlphabet { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', // special characters - '-', '_', '?', ' ', '#', '+', '/', '*', '!', '\"', '§', '$', '%', '&', '(', ')', '=', '@', + '-', '_', '?', ' ', '#', '+', '/', '*', '!', '"', '§', '$', '%', '&', '(', ')', '=', '@', '€', ',', ';', '.', ':', '<', '>', '|', '\'', '\\', '{', '}', '[', ']', // german special characters 'ä', 'Ä', 'ö', 'Ö', 'ü', 'Ü', 'ß' }; + /** + * Creates a new MainAlphabet instance. + * + *

This constructor performs no runtime initialization because the + * alphabet is represented by the static {@code ALL_CHARS} array. Use + * {@link #availableCharacters()} to obtain the supported characters and + * {@link #radix()} to obtain the alphabet size.

+ * + *

Important usage notes:

+ *
    + *
  • The array returned by {@link #availableCharacters()} is the internal + * static array; callers must not modify it.
  • + *
  • The alphabet intentionally contains letters (lower and upper case), + * digits, common punctuation and a set of German-specific characters + * to support locale-sensitive operations.
  • + *
+ */ + public MainAlphabet() { + // default constructor only ... + } + /** * Gets the available characters. - * @return + * + * @return an array containing all supported characters in the alphabet */ @Override public char[] availableCharacters() { @@ -39,7 +63,8 @@ public class MainAlphabet extends BaseAlphabet { /** * Gets the radix of the alphabet. - * @return + * + * @return the number of characters in the alphabet (radix) */ @Override public Integer radix() { diff --git a/encryption/src/main/java/de/neitzel/encryption/MainDomain.java b/encryption/src/main/java/de/neitzel/encryption/MainDomain.java index 573a633..221d9e2 100644 --- a/encryption/src/main/java/de/neitzel/encryption/MainDomain.java +++ b/encryption/src/main/java/de/neitzel/encryption/MainDomain.java @@ -4,26 +4,60 @@ import com.idealista.fpe.config.Alphabet; import com.idealista.fpe.config.Domain; import com.idealista.fpe.config.GenericTransformations; +/** + * Domain implementation that provides the alphabet and transformation helpers + * used by the format-preserving encryption implementation in this project. + *

+ * This class delegates character-to-index and index-to-character transformations + * to a {@link GenericTransformations} helper configured with the {@link MainAlphabet}. + */ public class MainDomain implements Domain { + /** + * The alphabet used by the domain for encoding/decoding characters. + */ private Alphabet _alphabet; + + /** + * Helper instance performing actual transformations between characters and indices. + */ private GenericTransformations transformations; + /** + * Constructs a new {@code MainDomain} instance and initializes its alphabet and transformation helper. + */ public MainDomain() { _alphabet = new MainAlphabet(); transformations = new GenericTransformations(_alphabet.availableCharacters()); } + /** + * Returns the {@link Alphabet} implementation used by this domain. + * + * @return the alphabet used for transforming values in this domain + */ @Override public Alphabet alphabet() { return _alphabet; } + /** + * Transforms a string of characters into an array of integer indices according to the configured alphabet. + * + * @param data the input string to transform; may not be null + * @return an integer array representing the indices of the characters in the given string + */ @Override public int[] transform(String data) { return transformations.transform(data); } + /** + * Transforms an array of integer indices back into a string using the configured alphabet. + * + * @param data the array of indices to transform back into characters + * @return the resulting string produced from the given index array + */ @Override public String transform(int[] data) { return transformations.transform(data); diff --git a/fx-example/pom.xml b/fx-example/pom.xml index 562daf0..7dca1fb 100644 --- a/fx-example/pom.xml +++ b/fx-example/pom.xml @@ -1,6 +1,6 @@ - 4.0.0 diff --git a/fx-example/src/main/java/de/neitzel/fx/component/example/Address.java b/fx-example/src/main/java/de/neitzel/fx/component/example/Address.java index 9166a04..e1a13cb 100644 --- a/fx-example/src/main/java/de/neitzel/fx/component/example/Address.java +++ b/fx-example/src/main/java/de/neitzel/fx/component/example/Address.java @@ -3,9 +3,27 @@ package de.neitzel.fx.component.example; import lombok.Getter; import lombok.Setter; +/** + * Simple address model used in the FX example component. + */ @Getter @Setter public class Address { + + /** + * Street name and number. + */ private String street; + + /** + * City name. + */ private String city; + + /** + * Default constructor only + */ + public Address() { + // default constructor only + } } \ No newline at end of file diff --git a/fx-example/src/main/java/de/neitzel/fx/component/example/ExampleApp.java b/fx-example/src/main/java/de/neitzel/fx/component/example/ExampleApp.java index d4ef74e..8eed94d 100644 --- a/fx-example/src/main/java/de/neitzel/fx/component/example/ExampleApp.java +++ b/fx-example/src/main/java/de/neitzel/fx/component/example/ExampleApp.java @@ -6,8 +6,32 @@ import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; +/** + * Example JavaFX application demonstrating the {@link de.neitzel.fx.component.ComponentLoader} usage. + */ public class ExampleApp extends Application { + /** + * Default constructor only + */ + public ExampleApp() { + // default constructor only + } + + /** + * Launches the JavaFX application. + * + * @param args command line arguments + */ + public static void main(String[] args) { + launch(args); + } + + /** + * Initializes sample model data, loads the FX component and shows the primary stage. + * + * @param primaryStage the primary stage for this application + */ @Override public void start(Stage primaryStage) throws Exception { // Beispielmodel initialisieren @@ -29,8 +53,4 @@ public class ExampleApp extends Application { primaryStage.setScene(scene); primaryStage.show(); } - - public static void main(String[] args) { - launch(); - } } \ No newline at end of file diff --git a/fx-example/src/main/java/de/neitzel/fx/component/example/Main.java b/fx-example/src/main/java/de/neitzel/fx/component/example/Main.java index 80565bb..4ac3c9b 100644 --- a/fx-example/src/main/java/de/neitzel/fx/component/example/Main.java +++ b/fx-example/src/main/java/de/neitzel/fx/component/example/Main.java @@ -5,8 +5,17 @@ package de.neitzel.fx.component.example; * taking care os Classloader Requirements of JavaFX. (Important when starting from inside NetBeans!) */ public class Main { + + /** + * Default constructor only + */ + public Main() { + // default constructor only + } + /** * Additional main methode to start Application. + * * @param args Commandline Arguments. */ public static void main(String[] args) { diff --git a/fx-example/src/main/java/de/neitzel/fx/component/example/Person.java b/fx-example/src/main/java/de/neitzel/fx/component/example/Person.java index 2078450..e77a086 100644 --- a/fx-example/src/main/java/de/neitzel/fx/component/example/Person.java +++ b/fx-example/src/main/java/de/neitzel/fx/component/example/Person.java @@ -3,9 +3,27 @@ package de.neitzel.fx.component.example; import lombok.Getter; import lombok.Setter; +/** + * Simple person model used in the FX example component. + */ @Getter @Setter public class Person { + + /** + * The person's full name. + */ private String name; + + /** + * The address of the person. + */ private Address address; + + /** + * Default constructor only + */ + public Person() { + // default constructor only + } } diff --git a/fx-example/src/main/java/de/neitzel/fx/injectfx/example/JavaFXApp.java b/fx-example/src/main/java/de/neitzel/fx/injectfx/example/JavaFXApp.java index 2020ead..cf3b85f 100644 --- a/fx-example/src/main/java/de/neitzel/fx/injectfx/example/JavaFXApp.java +++ b/fx-example/src/main/java/de/neitzel/fx/injectfx/example/JavaFXApp.java @@ -6,23 +6,44 @@ import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Minimal JavaFX application launcher used by the examples. + * + *

This class initializes the JavaFX runtime, loads {@code MainWindow.fxml} and shows + * the primary stage. It is intended as a small bootstrap used by IDEs or test runs + * to start the JavaFX UI for demonstration purposes. + */ public class JavaFXApp extends Application { - @Override - public void start(Stage primaryStage) { - try { - primaryStage.setTitle("Hello World!"); - FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MainWindow.fxml")); - Parent root = fxmlLoader.load(); - primaryStage.setScene(new Scene(root)); - primaryStage.show(); - } catch (Exception ex) { - System.out.println("Exception: " + ex.getMessage()); - ex.printStackTrace(); - } - } + private static final Logger LOGGER = Logger.getLogger(JavaFXApp.class.getName()); - public static void main(String[] args) { - launch(args); - } + /** + * Default constructor only. + * + *

The constructor does not perform UI initialization. UI setup happens in {@link #start(Stage)} + * after JavaFX has set up the application thread. + */ + public JavaFXApp() { + // default constructor only + } + + public static void main(String[] args) { + launch(args); + } + + @Override + public void start(Stage primaryStage) { + try { + primaryStage.setTitle("Hello World!"); + FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MainWindow.fxml")); + Parent root = fxmlLoader.load(); + primaryStage.setScene(new Scene(root)); + primaryStage.show(); + } catch (Exception ex) { + LOGGER.log(Level.SEVERE, "Exception while starting JavaFXApp", ex); + } + } } diff --git a/fx-example/src/main/java/de/neitzel/fx/injectfx/example/Main.java b/fx-example/src/main/java/de/neitzel/fx/injectfx/example/Main.java index 63b5774..20e7997 100644 --- a/fx-example/src/main/java/de/neitzel/fx/injectfx/example/Main.java +++ b/fx-example/src/main/java/de/neitzel/fx/injectfx/example/Main.java @@ -5,8 +5,26 @@ package de.neitzel.fx.injectfx.example; * taking care os Classloader Requirements of JavaFX. (Important when starting from inside NetBeans!) */ public class Main { + + /** + * Creates a new helper instance of {@code Main}. + * + *

This constructor is intentionally empty. The {@code Main} class serves as an alternative + * entry point to launch the JavaFX application via {@link JavaFXApp#main(String[])} in + * environments (IDEs, build tools) where directly starting a class that extends + * {@code javafx.application.Application} may fail due to classloader or JVM startup constraints. + * + *

Do not perform application initialization here; use the static {@code main} method to + * start the JavaFX runtime. This constructor exists to allow tooling and frameworks to + * instantiate the class reflectively if required. + */ + public Main() { + // default constructor only + } + /** * Additional main methode to start Application. + * * @param args Commandline Arguments. */ public static void main(String[] args) { diff --git a/fx-example/src/main/java/de/neitzel/fx/injectfx/example/MainWindow.java b/fx-example/src/main/java/de/neitzel/fx/injectfx/example/MainWindow.java index 07fa5c2..8418183 100644 --- a/fx-example/src/main/java/de/neitzel/fx/injectfx/example/MainWindow.java +++ b/fx-example/src/main/java/de/neitzel/fx/injectfx/example/MainWindow.java @@ -8,13 +8,49 @@ import javafx.scene.control.TextField; import java.net.URL; import java.util.ResourceBundle; +/** + * Controller for the MainWindow FXML view. + * + *

This class acts as the backing controller for the {@code MainWindow.fxml} UI. It demonstrates a + * minimal example of a JavaFX controller that: + *

    + *
  • receives UI element injection via {@link FXML} (the {@link #textField} field),
  • + *
  • initializes the view in {@link #initialize(URL, ResourceBundle)}, and
  • + *
  • handles user actions via {@link #onButtonClick(ActionEvent)}.
  • + *
+ * + *

Usage notes: + *

    + *
  • Fields annotated with {@link FXML} are injected by the {@code FXMLLoader} before + * {@link #initialize(URL, ResourceBundle)} is called — do not expect them to be non-null + * in the constructor.
  • + *
  • All UI updates must run on the JavaFX Application Thread. Methods called by FXML + * (such as {@link #onButtonClick(ActionEvent)}) are executed on that thread by the + * JavaFX runtime.
  • + *
  • The controller keeps a simple click counter and updates {@link #textField} to reflect + * the current count using {@link #displayCounter()}.
  • + *
+ */ public class MainWindow implements Initializable { + /** + * Counter for button clicks shown in the UI. + */ private int counter = 0; + /** + * Text field UI control showing the click counter. + */ @FXML private TextField textField; + /** + * Default constructor only + */ + public MainWindow() { + // default constructor only + } + @Override public void initialize(URL location, ResourceBundle resources) { displayCounter(); diff --git a/fx-example/src/main/resources/address.fxml b/fx-example/src/main/resources/address.fxml index 0fc914f..ae8f780 100644 --- a/fx-example/src/main/resources/address.fxml +++ b/fx-example/src/main/resources/address.fxml @@ -2,9 +2,9 @@ - diff --git a/fx-example/src/main/resources/de/neitzel/fx/injectfx/example/MainWindow.fxml b/fx-example/src/main/resources/de/neitzel/fx/injectfx/example/MainWindow.fxml index f213ab1..2ee1eea 100644 --- a/fx-example/src/main/resources/de/neitzel/fx/injectfx/example/MainWindow.fxml +++ b/fx-example/src/main/resources/de/neitzel/fx/injectfx/example/MainWindow.fxml @@ -3,9 +3,11 @@ - - -