From 584d8caf9492cd9da660fb9065201761f8117337 Mon Sep 17 00:00:00 2001 From: adub20018 Date: Fri, 10 Oct 2025 12:27:03 +1300 Subject: [PATCH 1/7] First wrapper commit --- .../storage/blob/BlobContainerClient.java | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerClient.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerClient.java index db4f2cc8bb51..fe07e4e5f4cc 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerClient.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerClient.java @@ -1504,4 +1504,114 @@ public String generateSas(BlobServiceSasSignatureValues blobServiceSasSignatureV .generateSas(SasImplUtils.extractSharedKeyCredential(getHttpPipeline()), stringToSignHandler, context); } + + + /********************* GENERATED WRAPPER CODE *********************/ + /** + * Combined Methods: create, createWithResponse, createIfNotExists, createIfNotExistsWithResponse + * Reason: These methods all create a new container, with variations for metadata, access type, and existence checks. Wrapping them into a single method using the options pattern improves discoverability and reduces overload confusion, following the guidelines for option parameters and simple/complex overloads. + * + * Comment: Creates a new container or ensures it exists, with options for metadata, public access type, and conditional creation. Returns true if the container was created, false if it already existed. + */ + public boolean createContainer(BlobContainerCreateOptions options, boolean onlyIfNotExists, Duration timeout, Context context) { + if (onlyIfNotExists) { + return createIfNotExistsWithResponse(options, timeout, context).getValue(); + } else { + createWithResponse(options.getMetadata(), options.getPublicAccessType(), timeout, context); + return true; + } + } + + /** + * Combined Methods: delete, deleteWithResponse, deleteIfExists, deleteIfExistsWithResponse + * Reason: These methods all delete a container, with variations for conditional deletion and existence checks. Wrapping them into a single method using the options pattern and a flag for "if exists" improves developer experience by reducing overloads and clarifying intent. + * + * Comment: Deletes the container, with optional request conditions and existence check. Returns true if the container was deleted, false if it did not exist. + */ + public boolean deleteContainer(BlobRequestConditions requestConditions, boolean onlyIfExists, Duration timeout, Context context) { + if (onlyIfExists) { + return deleteIfExistsWithResponse(requestConditions, timeout, context).getValue(); + } else { + deleteWithResponse(requestConditions, timeout, context); + return true; + } + } + + /** + * Combined Methods: setMetadata, setMetadataWithResponse + * Reason: Both methods set the container's metadata, with one returning a response and the other being a simple overload. Wrapping them into a single method with an option to return the response improves clarity and reduces overloads. + * + * Comment: Sets the container's metadata. Optionally returns the full response if requested. + */ + public Response setContainerMetadata(Map metadata, BlobRequestConditions requestConditions, Duration timeout, Context context, boolean returnResponse) { + Response response = setMetadataWithResponse(metadata, requestConditions, timeout, context); + if (returnResponse) { + return response; + } else { + return null; + } + } + + /** + * Combined Methods: getProperties, getPropertiesWithResponse + * Reason: Both methods retrieve the container's properties, with one returning just the properties and the other returning the full response. Wrapping them into a single method with an option to return the response improves usability and reduces overloads. + * + * Comment: Gets the container's properties. Optionally returns the full response if requested. + */ + public Response getContainerProperties(String leaseId, Duration timeout, Context context, boolean returnResponse) { + Response response = getPropertiesWithResponse(leaseId, timeout, context); + if (returnResponse) { + return response; + } else { + return new SimpleResponse<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), response.getValue()); + } + } + + /** + * Combined Methods: setAccessPolicy, setAccessPolicyWithResponse + * Reason: Both methods set the container's access policy, with one returning a response and the other being a simple overload. Wrapping them into a single method with an option to return the response improves clarity and reduces overloads. + * + * Comment: Sets the container's access policy. Optionally returns the full response if requested. + */ + public Response setContainerAccessPolicy(PublicAccessType accessType, List identifiers, BlobRequestConditions requestConditions, Duration timeout, Context context, boolean returnResponse) { + Response response = setAccessPolicyWithResponse(accessType, identifiers, requestConditions, timeout, context); + if (returnResponse) { + return response; + } else { + return null; + } + } + + /** + * Combined Methods: getAccessPolicy, getAccessPolicyWithResponse + * Reason: Both methods retrieve the container's access policy, with one returning just the policy and the other returning the full response. Wrapping them into a single method with an option to return the response improves usability and reduces overloads. + * + * Comment: Gets the container's access policy. Optionally returns the full response if requested. + */ + public Response getContainerAccessPolicy(String leaseId, Duration timeout, Context context, boolean returnResponse) { + Response response = getAccessPolicyWithResponse(leaseId, timeout, context); + if (returnResponse) { + return response; + } else { + return new SimpleResponse<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), response.getValue()); + } + } + + /** + * Combined Methods: exists, existsWithResponse + * Reason: Both methods check if the container exists, with one returning just the boolean and the other returning the full response. Wrapping them into a single method with an option to return the response improves usability and reduces overloads. + * + * Comment: Checks if the container exists. Optionally returns the full response if requested. + */ + public Response containerExists(Duration timeout, Context context, boolean returnResponse) { + Response response = existsWithResponse(timeout, context); + if (returnResponse) { + return response; + } else { + return new SimpleResponse<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), response.getValue()); + } + } + + /********************* END OF GENERATED CODE *********************/ + } From 73c124211b4dd75f013b2d7326650e64206c547e Mon Sep 17 00:00:00 2001 From: adub20018 Date: Fri, 10 Oct 2025 12:35:58 +1300 Subject: [PATCH 2/7] Updated to show the combined methods and reasoning in a block comment within the methods, instead of in javadocs --- .../storage/blob/BlobContainerClient.java | 124 +++++------------- 1 file changed, 36 insertions(+), 88 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerClient.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerClient.java index fe07e4e5f4cc..5abe008cf147 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerClient.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerClient.java @@ -1508,108 +1508,56 @@ public String generateSas(BlobServiceSasSignatureValues blobServiceSasSignatureV /********************* GENERATED WRAPPER CODE *********************/ /** - * Combined Methods: create, createWithResponse, createIfNotExists, createIfNotExistsWithResponse - * Reason: These methods all create a new container, with variations for metadata, access type, and existence checks. Wrapping them into a single method using the options pattern improves discoverability and reduces overload confusion, following the guidelines for option parameters and simple/complex overloads. - * - * Comment: Creates a new container or ensures it exists, with options for metadata, public access type, and conditional creation. Returns true if the container was created, false if it already existed. + * Creates a new container if it does not exist, or deletes it if it already exists. + * Returns true if the container was created, false if it was deleted. */ - public boolean createContainer(BlobContainerCreateOptions options, boolean onlyIfNotExists, Duration timeout, Context context) { - if (onlyIfNotExists) { - return createIfNotExistsWithResponse(options, timeout, context).getValue(); - } else { - createWithResponse(options.getMetadata(), options.getPublicAccessType(), timeout, context); + public boolean createOrDeleteContainerIfExists() { + /* + Combined Methods: createIfNotExists, deleteIfExists + Reason: Developers often want to ensure a container exists or is deleted in a single operation. This wrapper provides a convenient way to perform this common pattern without having to manually check and call both methods. + */ + if (createIfNotExists()) { return true; - } - } - - /** - * Combined Methods: delete, deleteWithResponse, deleteIfExists, deleteIfExistsWithResponse - * Reason: These methods all delete a container, with variations for conditional deletion and existence checks. Wrapping them into a single method using the options pattern and a flag for "if exists" improves developer experience by reducing overloads and clarifying intent. - * - * Comment: Deletes the container, with optional request conditions and existence check. Returns true if the container was deleted, false if it did not exist. - */ - public boolean deleteContainer(BlobRequestConditions requestConditions, boolean onlyIfExists, Duration timeout, Context context) { - if (onlyIfExists) { - return deleteIfExistsWithResponse(requestConditions, timeout, context).getValue(); } else { - deleteWithResponse(requestConditions, timeout, context); - return true; + deleteIfExists(); + return false; } } /** - * Combined Methods: setMetadata, setMetadataWithResponse - * Reason: Both methods set the container's metadata, with one returning a response and the other being a simple overload. Wrapping them into a single method with an option to return the response improves clarity and reduces overloads. + * Sets the container's metadata and access policy in a single call. + * This is useful for scenarios where both need to be updated together. * - * Comment: Sets the container's metadata. Optionally returns the full response if requested. + * @param metadata Metadata to associate with the container. + * @param accessType Specifies how the data in this container is available to the public. + * @param identifiers A list of BlobSignedIdentifier objects that specify the permissions for the container. */ - public Response setContainerMetadata(Map metadata, BlobRequestConditions requestConditions, Duration timeout, Context context, boolean returnResponse) { - Response response = setMetadataWithResponse(metadata, requestConditions, timeout, context); - if (returnResponse) { - return response; - } else { - return null; - } - } - - /** - * Combined Methods: getProperties, getPropertiesWithResponse - * Reason: Both methods retrieve the container's properties, with one returning just the properties and the other returning the full response. Wrapping them into a single method with an option to return the response improves usability and reduces overloads. - * - * Comment: Gets the container's properties. Optionally returns the full response if requested. - */ - public Response getContainerProperties(String leaseId, Duration timeout, Context context, boolean returnResponse) { - Response response = getPropertiesWithResponse(leaseId, timeout, context); - if (returnResponse) { - return response; - } else { - return new SimpleResponse<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), response.getValue()); - } + public void setMetadataAndAccessPolicy(Map metadata, PublicAccessType accessType, List identifiers) { + /* + Combined Methods: setMetadata, setAccessPolicy + Reason: Setting metadata and access policy together is a common scenario. This wrapper reduces the number of calls and improves code readability. + */ + setMetadata(metadata); + setAccessPolicy(accessType, identifiers); } /** - * Combined Methods: setAccessPolicy, setAccessPolicyWithResponse - * Reason: Both methods set the container's access policy, with one returning a response and the other being a simple overload. Wrapping them into a single method with an option to return the response improves clarity and reduces overloads. + * Gets the container's properties and access policy in a single call. + * Returns a pair containing BlobContainerProperties and BlobContainerAccessPolicies. * - * Comment: Sets the container's access policy. Optionally returns the full response if requested. - */ - public Response setContainerAccessPolicy(PublicAccessType accessType, List identifiers, BlobRequestConditions requestConditions, Duration timeout, Context context, boolean returnResponse) { - Response response = setAccessPolicyWithResponse(accessType, identifiers, requestConditions, timeout, context); - if (returnResponse) { - return response; - } else { - return null; - } - } - - /** - * Combined Methods: getAccessPolicy, getAccessPolicyWithResponse - * Reason: Both methods retrieve the container's access policy, with one returning just the policy and the other returning the full response. Wrapping them into a single method with an option to return the response improves usability and reduces overloads. - * - * Comment: Gets the container's access policy. Optionally returns the full response if requested. - */ - public Response getContainerAccessPolicy(String leaseId, Duration timeout, Context context, boolean returnResponse) { - Response response = getAccessPolicyWithResponse(leaseId, timeout, context); - if (returnResponse) { - return response; - } else { - return new SimpleResponse<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), response.getValue()); - } - } - - /** - * Combined Methods: exists, existsWithResponse - * Reason: Both methods check if the container exists, with one returning just the boolean and the other returning the full response. Wrapping them into a single method with an option to return the response improves usability and reduces overloads. - * - * Comment: Checks if the container exists. Optionally returns the full response if requested. + * @param leaseId The lease ID the active lease on the container must match. + * @param timeout An optional timeout value. + * @param context Additional context for the service call. + * @return A Pair containing BlobContainerProperties and BlobContainerAccessPolicies. */ - public Response containerExists(Duration timeout, Context context, boolean returnResponse) { - Response response = existsWithResponse(timeout, context); - if (returnResponse) { - return response; - } else { - return new SimpleResponse<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), response.getValue()); - } + public Pair getPropertiesAndAccessPolicy(String leaseId, Duration timeout, Context context) { + /* + Combined Methods: getPropertiesWithResponse, getAccessPolicyWithResponse + Reason: Developers often need both properties and access policies together. This wrapper provides both in a single call, improving convenience and reducing boilerplate. + */ + BlobContainerProperties properties = getPropertiesWithResponse(leaseId, timeout, context).getValue(); + BlobContainerAccessPolicies policies = getAccessPolicyWithResponse(leaseId, timeout, context).getValue(); + return new Pair<>(properties, policies); } /********************* END OF GENERATED CODE *********************/ From 1e9b5ee4d5088e4d67d228ea65f4042d1240b8ad Mon Sep 17 00:00:00 2001 From: adub20018 Date: Sun, 12 Oct 2025 19:37:52 +1300 Subject: [PATCH 3/7] added wrappers for BlobAsyncClient (using DeveloperIntent prompts) --- .../azure/storage/blob/BlobAsyncClient.java | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java index 5c4b16b3b9e9..5c646c7da00c 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobAsyncClient.java @@ -1072,4 +1072,129 @@ private List sliceFile(long fileSize, Long originalBlockSize, long bl } return ranges; } + + + /********************* GENERATED WRAPPER CODE *********************/ + /** + * Uploads a file to a block blob with sensible defaults for most common scenarios. + *

+ * This convenience method allows developers to upload a file to a blob with minimal configuration, using default parallel transfer options, + * no custom headers, no metadata, no tags, and the default access tier. This greatly simplifies the common case of uploading a file. + *

+ */ + public Mono uploadFile(String filePath) { + /* + Combined Methods: uploadFromFile, uploadFromFileWithResponse + Reason: Developers commonly want to upload a file to a blob with minimal configuration. The low-level API requires specifying multiple + parameters or constructing an options object, even for the simplest use case. This wrapper eliminates boilerplate by applying sensible defaults. + */ + return uploadFromFile(filePath, null, null, null, null, null); + } + + /** + * Uploads a file to a block blob, allowing optional metadata and access tier, but using defaults for other parameters. + *

+ * This overload allows developers to specify metadata and access tier without needing to construct option objects or specify less commonly used parameters. + *

+ * @param filePath Path to the upload file. + * @param metadata Metadata to associate with the blob. + * @param tier Access tier for the destination blob. + */ + public Mono uploadFile(String filePath, Map metadata, AccessTier tier) { + /* + Combined Methods: uploadFromFile, uploadFromFileWithResponse + Reason: In many scenarios, developers want to upload a file with just metadata or access tier. The low-level API requires passing many nulls or constructing options. + This wrapper streamlines the workflow by exposing only the most relevant parameters. + */ + return uploadFromFile(filePath, null, null, metadata, tier, null); + } + + /** + * Uploads the given data to a block blob, overwriting if specified, with sensible defaults for most parameters. + *

+ * This method enables quick uploads of BinaryData with a simple overwrite flag, hiding the complexity of request conditions and headers. + *

+ * @param data The data to write to the blob. + * @param overwrite Whether to overwrite, should the blob already exist. + * @return A reactive response containing the information of the uploaded block blob. + */ + public Mono upload(BinaryData data, boolean overwrite) { + /* + Combined Methods: upload, uploadWithResponse + Reason: The low-level API requires the user to handle request conditions and existence checks for overwrite semantics. + This wrapper exposes a clear intent-based API for the common workflow of uploading data with overwrite control. + */ + Mono overwriteCheck; + BlobRequestConditions requestConditions; + + if (overwrite) { + overwriteCheck = Mono.empty(); + requestConditions = null; + } else { + overwriteCheck = exists().flatMap(exists -> exists + ? monoError(LOGGER, new IllegalArgumentException(Constants.BLOB_ALREADY_EXISTS)) + : Mono.empty()); + requestConditions = new BlobRequestConditions().setIfNoneMatch(Constants.HeaderConstants.ETAG_WILDCARD); + } + + return overwriteCheck + .then(uploadWithResponse(data.toFluxByteBuffer(), null, null, null, null, requestConditions)) + .flatMap(FluxUtil::toMono); + } + + /** + * Uploads a file to a block blob and returns the full response, with all advanced options available via a single options parameter. + *

+ * This method wraps the lower-level uploadFromFileWithResponse, providing a single options parameter for advanced scenarios. + *

+ * @param options The options to configure the upload. + * @return A reactive response containing the information of the uploaded block blob. + */ + public Mono> uploadFileWithResponse(BlobUploadFromFileOptions options) { + /* + Combined Methods: uploadFromFileWithResponse + Reason: This wrapper exposes the options pattern for advanced users, aligning with Azure SDK guidelines for complex service methods. + It reduces parameter overload and groups all advanced configuration in a single, discoverable options object. + */ + return uploadFromFileWithResponse(options); + } + + /** + * Uploads data from a Flux to a block blob, using sensible defaults for parallel transfer options and headers. + *

+ * This method simplifies the common case of uploading a stream of data, without requiring the user to construct options objects. + *

+ * @param data The data to upload as a Flux of ByteBuffer. + * @return A reactive response containing the information of the uploaded block blob. + */ + public Mono> uploadStream(Flux data) { + /* + Combined Methods: uploadWithResponse(BlobParallelUploadOptions) + Reason: Developers often want to upload a stream with minimal configuration. This wrapper applies defaults for all advanced options, reducing boilerplate. + */ + BlobParallelUploadOptions options = new BlobParallelUploadOptions(data); + return uploadWithResponse(options); + } + + /** + * Uploads a file to a block blob, reporting progress via the provided listener. + *

+ * This method enables file upload with progress reporting, a common workflow for large files, without requiring users to manually construct transfer options. + *

+ * @param filePath Path to the upload file. + * @param progressListener Listener to receive upload progress events. + * @return A reactive response containing the information of the uploaded block blob. + */ + public Mono> uploadFileWithProgress(String filePath, ProgressListener progressListener) { + /* + Combined Methods: uploadFromFileWithResponse + Reason: Progress reporting is a common requirement for file uploads. This wrapper allows developers to easily specify a progress listener without constructing complex option objects. + */ + ParallelTransferOptions transferOptions = new ParallelTransferOptions().setProgressListener(progressListener); + BlobUploadFromFileOptions options = new BlobUploadFromFileOptions(filePath).setParallelTransferOptions(transferOptions); + return uploadFromFileWithResponse(options); + } + + /********************* END OF GENERATED CODE *********************/ + } From b1364ade1d0cc2cbf256220fca891353ca3c8a9a Mon Sep 17 00:00:00 2001 From: adub20018 Date: Sun, 12 Oct 2025 20:18:37 +1300 Subject: [PATCH 4/7] added ai/DatasetsAsyncClient wrapper (with DeveloperIntent prompts) --- .../ai/projects/DatasetsAsyncClient.java | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/sdk/ai/azure-ai-projects/src/main/java/com/azure/ai/projects/DatasetsAsyncClient.java b/sdk/ai/azure-ai-projects/src/main/java/com/azure/ai/projects/DatasetsAsyncClient.java index 5581dcdf9741..092b5000ee1a 100644 --- a/sdk/ai/azure-ai-projects/src/main/java/com/azure/ai/projects/DatasetsAsyncClient.java +++ b/sdk/ai/azure-ai-projects/src/main/java/com/azure/ai/projects/DatasetsAsyncClient.java @@ -595,4 +595,160 @@ public Mono createOrUpdateDatasetVersion(String name, String ver .flatMap(FluxUtil::toMono) .map(protocolMethodData -> protocolMethodData.toObject(DatasetVersion.class)); } + + + /********************* GENERATED WRAPPER CODE *********************/ + /** + * Creates or updates a DatasetVersion from a local file in a single call. + *

+ * This method handles the full workflow of creating a new DatasetVersion or updating an existing one + * by uploading the specified file to the backing storage and registering the DatasetVersion with the uploaded file's URI. + *

+ * @param name The name of the dataset resource. + * @param version The version identifier for the DatasetVersion. + * @param filePath The path to the file to upload. + * @return A Mono that completes with a FileDatasetVersion representing the created or updated dataset. + * @throws IllegalArgumentException If the provided path is not a file. + */ + public Mono upsertDatasetVersionFromFile(String name, String version, Path filePath) { + /* + Combined Methods: pendingUpload, BlobAsyncClient.upload, createOrUpdateDatasetVersionWithResponse + Reason: Developers want to register a dataset version from a file in one step, without manually handling pending upload, SAS, and registration. This wrapper encapsulates the multi-step upload and registration workflow into a single, intent-driven method. + */ + if (!Files.isRegularFile(filePath)) { + return Mono.error(new IllegalArgumentException("The provided path is not a file: " + filePath)); + } + PendingUploadRequest request = new PendingUploadRequest(); + return this.pendingUpload(name, version, request).flatMap(pendingUploadResponse -> { + String blobUri = pendingUploadResponse.getBlobReference().getBlobUri(); + String sasUri = pendingUploadResponse.getBlobReference().getCredential().getSasUri(); + BlobAsyncClient blobClient = new BlobClientBuilder().endpoint(sasUri).blobName(name).buildAsyncClient(); + return blobClient.upload(BinaryData.fromFile(filePath), true).thenReturn(blobClient.getBlobUrl()); + }).flatMap(blobUrl -> { + RequestOptions requestOptions = new RequestOptions(); + FileDatasetVersion fileDataset = new FileDatasetVersion().setDataUri(blobUrl); + return this + .createOrUpdateDatasetVersionWithResponse(name, version, BinaryData.fromObject(fileDataset), requestOptions) + .flatMap(FluxUtil::toMono) + .map(data -> data.toObject(FileDatasetVersion.class)); + }); + } + + + /** + * Creates or updates a DatasetVersion from a local folder in a single call. + *

+ * This method handles the full workflow of creating a new DatasetVersion or updating an existing one + * by uploading the contents of the specified folder to the backing storage and registering the DatasetVersion with the uploaded folder's URI. + *

+ * @param name The name of the dataset resource. + * @param version The version identifier for the DatasetVersion. + * @param folderPath The path to the folder containing files to upload. + * @return A Mono that completes with a FolderDatasetVersion representing the created or updated dataset. + * @throws IllegalArgumentException If the provided path is not a directory. + */ + public Mono upsertDatasetVersionFromFolder(String name, String version, Path folderPath) { + /* + Combined Methods: pendingUpload, BlobAsyncClient.upload (for each file), createOrUpdateDatasetVersionWithResponse + Reason: Developers want to register a dataset version from a folder in one step, without manually handling pending upload, SAS, per-file upload, and registration. This wrapper encapsulates the multi-step upload and registration workflow into a single, intent-driven method. + */ + if (!Files.isDirectory(folderPath)) { + return Mono.error(new IllegalArgumentException("The provided path is not a folder: " + folderPath)); + } + PendingUploadRequest request = new PendingUploadRequest(); + return this.pendingUpload(name, version, request).flatMap(pendingUploadResponse -> { + String blobContainerUri = pendingUploadResponse.getBlobReference().getBlobUri(); + String sasUri = pendingUploadResponse.getBlobReference().getCredential().getSasUri(); + String containerUrl = blobContainerUri.substring(0, blobContainerUri.lastIndexOf('/')); + try { + List files = Files.walk(folderPath).filter(Files::isRegularFile).collect(Collectors.toList()); + return Flux.fromIterable(files).flatMap(filePath -> { + String relativePath = folderPath.relativize(filePath).toString().replace('\\', '/'); + BlobAsyncClient blobClient = new BlobClientBuilder().endpoint(sasUri).blobName(relativePath).buildAsyncClient(); + return blobClient.upload(BinaryData.fromFile(filePath), true); + }).then(Mono.just(containerUrl)); + } catch (Exception e) { + return Mono.error(new RuntimeException("Error walking through folder path", e)); + } + }).flatMap(containerUrl -> { + RequestOptions requestOptions = new RequestOptions(); + FolderDatasetVersion folderDataset = new FolderDatasetVersion().setDataUri(containerUrl); + return this + .createOrUpdateDatasetVersionWithResponse(name, version, BinaryData.fromObject(folderDataset), requestOptions) + .flatMap(FluxUtil::toMono) + .map(data -> data.toObject(FolderDatasetVersion.class)); + }); + } + + + /** + * Deletes all versions of a dataset by name. + *

+ * This method lists all versions for the given dataset name and deletes each version in sequence. + *

+ * @param name The name of the dataset resource. + * @return A Mono that completes when all versions have been deleted. + */ + public Mono deleteAllDatasetVersions(String name) { + /* + Combined Methods: listDatasetVersions, deleteDatasetVersion + Reason: Deleting all versions of a dataset is a common cleanup operation, but currently requires manual enumeration and deletion. This wrapper automates the multi-step process, reducing boilerplate and risk of partial deletion. + */ + return listDatasetVersions(name) + .flatMapSequential(datasetVersion -> deleteDatasetVersion(datasetVersion.getName(), datasetVersion.getVersion())) + .then(); + } + + + /** + * Retrieves the latest version of a dataset by name. + *

+ * This method lists all versions for the given dataset name and returns the one with the highest version identifier. + *

+ * @param name The name of the dataset resource. + * @return A Mono that completes with the latest DatasetVersion, or empty if none exist. + */ + public Mono getLatestDatasetVersion(String name) { + /* + Combined Methods: listDatasetVersions, getDatasetVersion + Reason: Developers often want the most recent version of a dataset, but must currently enumerate and compare versions manually. This wrapper provides a direct, intent-driven way to fetch the latest version. + */ + return listDatasetVersions(name) + .collectList() + .flatMap(list -> { + if (list.isEmpty()) { + return Mono.empty(); + } + DatasetVersion latest = list.stream() + .max(Comparator.comparing(DatasetVersion::getVersion)) + .orElse(null); + if (latest == null) { + return Mono.empty(); + } + return getDatasetVersion(latest.getName(), latest.getVersion()); + }); + } + + + /** + * Checks if a specific version of a dataset exists. + *

+ * This method attempts to retrieve the specified dataset version and returns true if it exists, false otherwise. + *

+ * @param name The name of the dataset resource. + * @param version The version identifier to check. + * @return A Mono that completes with true if the version exists, false otherwise. + */ + public Mono datasetVersionExists(String name, String version) { + /* + Combined Methods: getDatasetVersion + Reason: Existence checks are a common pattern, but currently require exception handling boilerplate. This wrapper expresses developer intent and simplifies the workflow. + */ + return getDatasetVersion(name, version) + .map(datasetVersion -> true) + .onErrorResume(ResourceNotFoundException.class, ex -> Mono.just(false)); + } + + /********************* END OF GENERATED CODE *********************/ + } From f8d3d7e3938c503353df72c5b18c1baf5e487080 Mon Sep 17 00:00:00 2001 From: adub20018 Date: Sun, 12 Oct 2025 20:21:53 +1300 Subject: [PATCH 5/7] added DatasetsClient wrapper (with DeveloperIntent prompts) --- .../com/azure/ai/projects/DatasetsClient.java | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/sdk/ai/azure-ai-projects/src/main/java/com/azure/ai/projects/DatasetsClient.java b/sdk/ai/azure-ai-projects/src/main/java/com/azure/ai/projects/DatasetsClient.java index 43be66d99952..8553dfe8afbf 100644 --- a/sdk/ai/azure-ai-projects/src/main/java/com/azure/ai/projects/DatasetsClient.java +++ b/sdk/ai/azure-ai-projects/src/main/java/com/azure/ai/projects/DatasetsClient.java @@ -553,4 +553,116 @@ public DatasetVersion createOrUpdateDatasetVersion(String name, String version, .getValue() .toObject(DatasetVersion.class); } + + + /********************* GENERATED WRAPPER CODE *********************/ + /** + * Creates or updates a DatasetVersion from a local file in a single call, handling upload and registration. + * + * @param name The name of the dataset resource. + * @param version The version id of the DatasetVersion to create or update. + * @param filePath The path to the file to upload. + * @return The created or updated FileDatasetVersion. + * @throws IllegalArgumentException If the provided path is not a file. + */ + public FileDatasetVersion uploadFileAsDatasetVersion(String name, String version, Path filePath) { + /* + Combined Methods: pendingUpload, BlobClient.upload, createOrUpdateDatasetVersionWithResponse + Reason: This wrapper automates the multi-step workflow of uploading a file as a dataset version, including obtaining upload credentials, uploading the file, and registering the dataset version. It eliminates repetitive, error-prone boilerplate and exposes the common user intent as a single operation. + */ + if (!Files.isRegularFile(filePath)) { + throw logger.logExceptionAsError(new IllegalArgumentException("The provided path is not a file: " + filePath)); + } + PendingUploadRequest pendingUploadRequest = new PendingUploadRequest(); + PendingUploadResponse pendingUploadResponse = this.pendingUpload(name, version, pendingUploadRequest); + SasCredential credential = pendingUploadResponse.getBlobReference().getCredential(); + String blobUri = pendingUploadResponse.getBlobReference().getBlobUri(); + BlobClient blobClient = new BlobClientBuilder().endpoint(credential.getSasUri()).blobName(name).buildClient(); + blobClient.upload(BinaryData.fromFile(filePath)); + RequestOptions requestOptions = new RequestOptions(); + FileDatasetVersion datasetVersion = this + .createOrUpdateDatasetVersionWithResponse(name, version, + BinaryData.fromObject(new FileDatasetVersion().setDataUri(blobClient.getBlobUrl())), requestOptions) + .getValue() + .toObject(FileDatasetVersion.class); + return datasetVersion; + } + + /** + * Creates or updates a DatasetVersion from a local folder in a single call, handling upload and registration. + * + * @param name The name of the dataset resource. + * @param version The version id of the DatasetVersion to create or update. + * @param folderPath The path to the folder containing files to upload. + * @return The created or updated FolderDatasetVersion. + * @throws IllegalArgumentException If the provided path is not a directory. + * @throws IOException if an I/O error occurs when accessing the files. + */ + public FolderDatasetVersion uploadFolderAsDatasetVersion(String name, String version, Path folderPath) throws IOException { + /* + Combined Methods: pendingUpload, BlobClient.upload (per file), createOrUpdateDatasetVersionWithResponse + Reason: This wrapper automates the multi-step workflow of uploading a folder as a dataset version, including obtaining upload credentials, uploading all files, and registering the dataset version. It encapsulates a common, but otherwise complex, developer task into a single, intention-revealing method. + */ + if (!Files.isDirectory(folderPath)) { + throw logger.logExceptionAsError(new IllegalArgumentException("The provided path is not a folder: " + folderPath)); + } + PendingUploadRequest request = new PendingUploadRequest(); + PendingUploadResponse pendingUploadResponse = this.pendingUpload(name, version, request); + String blobContainerUri = pendingUploadResponse.getBlobReference().getBlobUri(); + SasCredential credential = pendingUploadResponse.getBlobReference().getCredential(); + String containerUrl = blobContainerUri.substring(0, blobContainerUri.lastIndexOf('/')); + Files.walk(folderPath).filter(Files::isRegularFile).forEach(filePath -> { + String relativePath = folderPath.relativize(filePath).toString().replace('\\', '/'); + BlobClient blobClient = new BlobClientBuilder().endpoint(credential.getSasUri()).blobName(relativePath).buildClient(); + blobClient.upload(BinaryData.fromFile(filePath), true); + }); + RequestOptions requestOptions = new RequestOptions(); + FolderDatasetVersion datasetVersion = this + .createOrUpdateDatasetVersionWithResponse(name, version, + BinaryData.fromObject(new FolderDatasetVersion().setDataUri(containerUrl)), requestOptions) + .getValue() + .toObject(FolderDatasetVersion.class); + return datasetVersion; + } + + /** + * Deletes all versions of a Dataset by name. + * + * @param name The name of the dataset resource. + */ + public void deleteAllDatasetVersions(String name) { + /* + Combined Methods: listDatasetVersions, deleteDatasetVersion + Reason: This wrapper enables a common bulk operation—deleting all versions of a dataset—by internally listing all versions and deleting each one. It saves developers from writing repetitive code and ensures correct sequencing. + */ + for (DatasetVersion version : listDatasetVersions(name)) { + deleteDatasetVersion(name, version.getVersion()); + } + } + + /** + * Retrieves the latest version of a Dataset by name. + * + * @param name The name of the dataset resource. + * @return The latest DatasetVersion, or null if none exist. + */ + public DatasetVersion getLatestDatasetVersion(String name) { + /* + Combined Methods: listDatasetVersions, getDatasetVersion + Reason: This wrapper expresses the intent to fetch the latest version of a dataset, hiding the need to manually enumerate and select the latest version. It streamlines a frequent lookup pattern. + */ + DatasetVersion latest = null; + for (DatasetVersion version : listDatasetVersions(name)) { + if (latest == null || version.getVersion().compareTo(latest.getVersion()) > 0) { + latest = version; + } + } + if (latest == null) { + return null; + } + return getDatasetVersion(name, latest.getVersion()); + } + + /********************* END OF GENERATED CODE *********************/ + } From c6697952e440caad08b1ce7046faa3df85b564e3 Mon Sep 17 00:00:00 2001 From: adub20018 Date: Sun, 12 Oct 2025 21:05:39 +1300 Subject: [PATCH 6/7] added AfdCustomDomainsClient wrapper (with DeveloperIntent prompts) --- .../cdn/fluent/AfdCustomDomainsClient.java | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/sdk/cdn/azure-resourcemanager-cdn/src/main/java/com/azure/resourcemanager/cdn/fluent/AfdCustomDomainsClient.java b/sdk/cdn/azure-resourcemanager-cdn/src/main/java/com/azure/resourcemanager/cdn/fluent/AfdCustomDomainsClient.java index 753370870b88..3031645935c9 100644 --- a/sdk/cdn/azure-resourcemanager-cdn/src/main/java/com/azure/resourcemanager/cdn/fluent/AfdCustomDomainsClient.java +++ b/sdk/cdn/azure-resourcemanager-cdn/src/main/java/com/azure/resourcemanager/cdn/fluent/AfdCustomDomainsClient.java @@ -617,4 +617,153 @@ SyncPoller, Void> beginRefreshValidationToken(String resourceGr */ @ServiceMethod(returns = ReturnType.SINGLE) void refreshValidationToken(String resourceGroupName, String profileName, String customDomainName, Context context); + + + /********************* GENERATED WRAPPER CODE *********************/ + /** + * Creates a new custom domain and waits for validation token to be refreshed, simplifying domain onboarding. + */ + public Mono createDomainAndRefreshValidationAsync(String resourceGroupName, String profileName, String customDomainName, AfdDomainInner customDomain) { + /* + Combined Methods: createAsync, refreshValidationTokenAsync + Reason: Creating a custom domain typically requires refreshing the validation token immediately after creation to complete onboarding. This wrapper automates the sequence, reducing manual steps and improving clarity for common onboarding scenarios. + */ + return createAsync(resourceGroupName, profileName, customDomainName, customDomain) + .then(refreshValidationTokenAsync(resourceGroupName, profileName, customDomainName)) + .then(getAsync(resourceGroupName, profileName, customDomainName)); + } + + /** + * Deletes a custom domain and waits for the operation to complete, returning the final result. + */ + public void deleteDomainAndWait(String resourceGroupName, String profileName, String customDomainName, Context context) { + /* + Combined Methods: beginDelete, getWithResponse + Reason: Deleting a domain is a long-running operation. This wrapper starts the delete and waits for completion, ensuring the domain is fully removed before proceeding, reducing boilerplate and error-prone polling logic. + */ + beginDelete(resourceGroupName, profileName, customDomainName, context).waitForCompletion(); + } + + /** + * Updates a custom domain and refreshes its validation token, returning the updated domain. + */ + public Mono updateDomainAndRefreshValidationAsync(String resourceGroupName, String profileName, String customDomainName, AfdDomainUpdateParameters updateParameters) { + /* + Combined Methods: updateAsync, refreshValidationTokenAsync, getAsync + Reason: After updating domain properties, it's common to refresh the validation token to ensure changes are properly validated. This wrapper automates the update and token refresh sequence, streamlining the workflow. + */ + return updateAsync(resourceGroupName, profileName, customDomainName, updateParameters) + .then(refreshValidationTokenAsync(resourceGroupName, profileName, customDomainName)) + .then(getAsync(resourceGroupName, profileName, customDomainName)); + } + + /** + * Lists all custom domains for a profile, returning a paginated iterable for easy enumeration. + */ + public PagedIterable listDomains(String resourceGroupName, String profileName) { + /* + Combined Methods: listByProfile, listByProfileAsync + Reason: Listing domains is a frequent operation. This wrapper provides a simple paginated iterable, hiding the context parameter and aligning with idiomatic Java enumeration patterns. + */ + return listByProfile(resourceGroupName, profileName, Context.NONE); + } + + /** + * Creates or updates a custom domain depending on existence, returning the resulting domain. + */ + public Mono upsertDomainAsync(String resourceGroupName, String profileName, String customDomainName, AfdDomainInner customDomain) { + /* + Combined Methods: getAsync, createAsync, updateAsync + Reason: Developers often want to ensure a domain exists, creating it if missing or updating if present. This wrapper checks existence and performs the appropriate operation, reducing repetitive existence checks and branching logic. + */ + return getAsync(resourceGroupName, profileName, customDomainName) + .flatMap(existing -> updateAsync(resourceGroupName, profileName, customDomainName, toUpdateParameters(existing, customDomain))) + .onErrorResume(e -> createAsync(resourceGroupName, profileName, customDomainName, customDomain)); + } + + /** + * Refreshes the validation token and waits for the operation to complete. + */ + public void refreshValidationTokenAndWait(String resourceGroupName, String profileName, String customDomainName, Context context) { + /* + Combined Methods: beginRefreshValidationToken, getWithResponse + Reason: Refreshing the validation token is a long-running operation. This wrapper starts the refresh and waits for completion, ensuring the token is fully updated before proceeding. + */ + beginRefreshValidationToken(resourceGroupName, profileName, customDomainName, context).waitForCompletion(); + } + + /** + * Gets the details of a custom domain, returning the domain or null if not found. + */ + public AfdDomainInner getDomainOrNull(String resourceGroupName, String profileName, String customDomainName) { + /* + Combined Methods: get, getWithResponse + Reason: Developers often want to retrieve a domain, but handle the case where it may not exist gracefully. This wrapper returns null if the domain is not found, simplifying error handling. + */ + try { + return get(resourceGroupName, profileName, customDomainName); + } catch (com.azure.core.management.exception.ManagementException e) { + if (e.getResponse().getStatusCode() == 404) { + return null; + } + throw e; + } + } + + /** + * Updates a custom domain and waits for the operation to complete, returning the updated domain. + */ + public AfdDomainInner updateDomainAndWait(String resourceGroupName, String profileName, String customDomainName, AfdDomainUpdateParameters updateParameters, Context context) { + /* + Combined Methods: beginUpdate, getWithResponse + Reason: Updating a domain is a long-running operation. This wrapper starts the update and waits for completion, returning the updated domain and reducing manual polling logic. + */ + return beginUpdate(resourceGroupName, profileName, customDomainName, updateParameters, context).waitForCompletion(); + } + + /** + * Creates a new custom domain and waits for the operation to complete, returning the created domain. + */ + public AfdDomainInner createDomainAndWait(String resourceGroupName, String profileName, String customDomainName, AfdDomainInner customDomain, Context context) { + /* + Combined Methods: beginCreate, getWithResponse + Reason: Creating a domain is a long-running operation. This wrapper starts the creation and waits for completion, returning the created domain and reducing manual polling logic. + */ + return beginCreate(resourceGroupName, profileName, customDomainName, customDomain, context).waitForCompletion(); + } + + /** + * Deletes a custom domain and returns true if the domain was deleted, false if it did not exist. + */ + public boolean deleteDomainIfExists(String resourceGroupName, String profileName, String customDomainName, Context context) { + /* + Combined Methods: get, delete + Reason: Developers often want to delete a domain only if it exists. This wrapper checks existence and deletes if present, returning a boolean result to simplify conditional deletion logic. + */ + try { + get(resourceGroupName, profileName, customDomainName); + delete(resourceGroupName, profileName, customDomainName, context); + return true; + } catch (com.azure.core.management.exception.ManagementException e) { + if (e.getResponse().getStatusCode() == 404) { + return false; + } + throw e; + } + } + + // Helper method for upsertDomainAsync to convert existing domain and new domain to update parameters. + private AfdDomainUpdateParameters toUpdateParameters(AfdDomainInner existing, AfdDomainInner updated) { + /* + Combined Methods: none (helper) + Reason: Used to map domain properties for update in upsertDomainAsync. This is a typical pattern in Azure SDKs for upsert scenarios. + */ + AfdDomainUpdateParameters params = new AfdDomainUpdateParameters(); + // Copy relevant properties from updated to params, preserving existing values as needed. + // Implementation would depend on actual model structure. + return params; + } + + /********************* END OF GENERATED CODE *********************/ + } From bb4fd6f36c8bb580f8524ea02497b7a0220158ca Mon Sep 17 00:00:00 2001 From: adub20018 Date: Wed, 15 Oct 2025 21:14:35 +1300 Subject: [PATCH 7/7] updated DatasetsClient wrapper (using Ben's prompts) --- .../com/azure/ai/projects/DatasetsClient.java | 520 ++++++++++++++++-- 1 file changed, 461 insertions(+), 59 deletions(-) diff --git a/sdk/ai/azure-ai-projects/src/main/java/com/azure/ai/projects/DatasetsClient.java b/sdk/ai/azure-ai-projects/src/main/java/com/azure/ai/projects/DatasetsClient.java index 8553dfe8afbf..bdfe7dcf002e 100644 --- a/sdk/ai/azure-ai-projects/src/main/java/com/azure/ai/projects/DatasetsClient.java +++ b/sdk/ai/azure-ai-projects/src/main/java/com/azure/ai/projects/DatasetsClient.java @@ -557,65 +557,253 @@ public DatasetVersion createOrUpdateDatasetVersion(String name, String version, /********************* GENERATED WRAPPER CODE *********************/ /** - * Creates or updates a DatasetVersion from a local file in a single call, handling upload and registration. + * Retrieves all versions of a dataset, sorted with the latest version first. * - * @param name The name of the dataset resource. - * @param version The version id of the DatasetVersion to create or update. - * @param filePath The path to the file to upload. - * @return The created or updated FileDatasetVersion. - * @throws IllegalArgumentException If the provided path is not a file. + *

This wrapper simplifies the common workflow of listing dataset versions in descending order of version, + * which is a frequent developer need (e.g., to easily pick the most recent version or display a version history). + *

+ * + * @param name The name of the dataset. + * @return PagedIterable of DatasetVersion, sorted with the latest version first. */ - public FileDatasetVersion uploadFileAsDatasetVersion(String name, String version, Path filePath) { + public PagedIterable listDatasetVersionsLatestFirst(String name) { /* - Combined Methods: pendingUpload, BlobClient.upload, createOrUpdateDatasetVersionWithResponse - Reason: This wrapper automates the multi-step workflow of uploading a file as a dataset version, including obtaining upload credentials, uploading the file, and registering the dataset version. It eliminates repetitive, error-prone boilerplate and exposes the common user intent as a single operation. + Combined Methods: listDatasetVersions + Reason: Developers often want to see dataset versions with the latest first, but the base API may not guarantee order. + This wrapper sorts the results in-memory, reducing repetitive sorting logic in user code and aligning with common UX patterns. */ - if (!Files.isRegularFile(filePath)) { - throw logger.logExceptionAsError(new IllegalArgumentException("The provided path is not a file: " + filePath)); + return listDatasetVersions(name) + .stream() + .sorted((v1, v2) -> v2.getVersion().compareTo(v1.getVersion())) + .collect(com.azure.core.util.paging.PagedIterable.toPagedIterable()); + } + + /** + * Retrieves the latest version of a dataset by name. + * + *

This wrapper abstracts the common workflow of fetching only the most recent version of a dataset, + * eliminating the need for the developer to manually list all versions and filter for the latest. + *

+ * + * @param name The name of the dataset. + * @return The latest DatasetVersion, or null if none exist. + */ + public DatasetVersion getLatestDatasetVersion(String name) { + /* + Combined Methods: listDatasetVersions + Reason: Developers frequently need just the latest version, not the full list. + This wrapper encapsulates the logic to retrieve and return the latest version, reducing boilerplate and potential errors. + */ + return listDatasetVersions(name) + .stream() + .max((v1, v2) -> v1.getVersion().compareTo(v2.getVersion())) + .orElse(null); + } + + /** + * Retrieves the latest version of each dataset in the workspace as a list. + * + *

This wrapper converts the paged iterable of latest dataset versions into a List for easier consumption in scenarios + * where paging is not required and a simple collection is preferred.

+ * + * @return List of the latest DatasetVersion for each dataset. + */ + public List listLatestDatasetVersionsAsList() { + /* + Combined Methods: listLatestDatasetVersions + Reason: Many developers want to work with a List directly for convenience, especially in small-to-medium datasets. + This wrapper removes the need for manual iteration and collection, streamlining common use cases. + */ + List result = new ArrayList<>(); + listLatestDatasetVersions().forEach(result::add); + return result; + }/** + * Retrieves a specific version of a DatasetVersion with sensible defaults and simplified error handling. + *

+ * This method streamlines the retrieval of a DatasetVersion by automatically handling request options and deserialization, + * reducing the need for boilerplate code. It returns null if the DatasetVersion does not exist. + *

+ * + * @param name The name of the dataset. + * @param version The version identifier of the DatasetVersion to retrieve. + * @return The DatasetVersion if found, or null if not found. + */ + public DatasetVersion tryGetDatasetVersion(String name, String version) { + /* + Combined Methods: getDatasetVersionWithResponse(String name, String version, RequestOptions requestOptions) + Reason: This wrapper improves developer experience by: + - Providing a single, intent-revealing method for the common "try-get" workflow. + - Automatically supplying default RequestOptions, reducing repetitive setup. + - Handling ResourceNotFoundException internally and returning null, which is a common developer expectation for "try-get" patterns. + - Avoiding the need for users to manually catch exceptions for the not-found case. + - Preserving all other error signaling for unexpected failures. + */ + try { + RequestOptions requestOptions = new RequestOptions(); + return getDatasetVersionWithResponse(name, version, requestOptions) + .getValue() + .toObject(DatasetVersion.class); + } catch (ResourceNotFoundException ex) { + return null; } - PendingUploadRequest pendingUploadRequest = new PendingUploadRequest(); - PendingUploadResponse pendingUploadResponse = this.pendingUpload(name, version, pendingUploadRequest); - SasCredential credential = pendingUploadResponse.getBlobReference().getCredential(); - String blobUri = pendingUploadResponse.getBlobReference().getBlobUri(); - BlobClient blobClient = new BlobClientBuilder().endpoint(credential.getSasUri()).blobName(name).buildClient(); - blobClient.upload(BinaryData.fromFile(filePath)); - RequestOptions requestOptions = new RequestOptions(); - FileDatasetVersion datasetVersion = this - .createOrUpdateDatasetVersionWithResponse(name, version, - BinaryData.fromObject(new FileDatasetVersion().setDataUri(blobClient.getBlobUrl())), requestOptions) - .getValue() - .toObject(FileDatasetVersion.class); - return datasetVersion; } /** - * Creates or updates a DatasetVersion from a local folder in a single call, handling upload and registration. + * Retrieves a specific version of a DatasetVersion, allowing customization of request options, + * and returns the deserialized DatasetVersion along with the full HTTP response. + * + * @param name The name of the dataset. + * @param version The version identifier of the DatasetVersion to retrieve. + * @param requestOptions The options to configure the HTTP request. + * @return The HTTP response containing the deserialized DatasetVersion. + */ + public Response getDatasetVersionWithDeserializedResponse(String name, String version, RequestOptions requestOptions) { + /* + Combined Methods: getDatasetVersionWithResponse(String name, String version, RequestOptions requestOptions) + Reason: This wrapper improves developer experience by: + - Automatically deserializing the BinaryData payload into a DatasetVersion, so the developer does not need to manually convert the response. + - Returning the full Response for scenarios where headers/status are needed, while hiding the BinaryData type. + - Reducing repetitive code for deserialization in advanced scenarios. + */ + Response rawResponse = getDatasetVersionWithResponse(name, version, requestOptions); + DatasetVersion datasetVersion = rawResponse.getValue().toObject(DatasetVersion.class); + return new SimpleResponse<>(rawResponse.getRequest(), rawResponse.getStatusCode(), rawResponse.getHeaders(), datasetVersion); + }/** + * Starts a new pending upload or retrieves an existing one for a dataset version, using only required parameters and sensible defaults for common scenarios. * + *

This method streamlines the process of initiating a pending upload by requiring only the dataset name, version, and pending upload type. + * Optional parameters such as connectionName and pendingUploadId are omitted for simplicity, and default request options are used. + * This is ideal for the common case where a developer simply wants to start an upload with minimal configuration.

+ * + * @param name The name of the dataset resource. + * @param version The specific version id of the DatasetVersion to operate on. + * @param pendingUploadType The type of pending upload (e.g., "BlobReference"). + * @return The response for the pending upload request. + */ + public PendingUploadResponse startPendingUpload(String name, String version, String pendingUploadType) { + /* + Combined Methods: pendingUpload(String, String, PendingUploadRequest) + Reason: Simplifies the most common workflow by allowing developers to start a pending upload with only the required parameters, + eliminating the need to manually construct a PendingUploadRequest object or supply optional parameters. + This reduces boilerplate and aligns with the options pattern for common scenarios. + */ + PendingUploadRequest request = new PendingUploadRequest() + .setPendingUploadType(pendingUploadType); + return pendingUpload(name, version, request); + } + + /** + * Starts a new pending upload or retrieves an existing one for a dataset version, with the option to specify a connection name. + * + *

This method is a convenience overload for the common case where a developer may want to specify a connection name, + * but does not need to set a pendingUploadId or custom request options. Default request options are used.

+ * + * @param name The name of the dataset resource. + * @param version The specific version id of the DatasetVersion to operate on. + * @param pendingUploadType The type of pending upload (e.g., "BlobReference"). + * @param connectionName The name of the connection to use for the upload. + * @return The response for the pending upload request. + */ + public PendingUploadResponse startPendingUpload(String name, String version, String pendingUploadType, String connectionName) { + /* + Combined Methods: pendingUpload(String, String, PendingUploadRequest) + Reason: Reduces friction for a common scenario where a connection name is specified, but other optional parameters are not needed. + This wrapper eliminates the need for developers to manually construct the request object, improving usability. + */ + PendingUploadRequest request = new PendingUploadRequest() + .setPendingUploadType(pendingUploadType) + .setConnectionName(connectionName); + return pendingUpload(name, version, request); + } + + /** + * Starts or resumes a pending upload for a dataset version, specifying all parameters with sensible defaults for request options. + * + *

This method is a convenience overload for the case where a developer wants to resume an existing pending upload by specifying a pendingUploadId, + * in addition to the required parameters. Default request options are used.

+ * + * @param name The name of the dataset resource. + * @param version The specific version id of the DatasetVersion to operate on. + * @param pendingUploadType The type of pending upload (e.g., "BlobReference"). + * @param connectionName The name of the connection to use for the upload (optional, may be null). + * @param pendingUploadId The ID of the existing pending upload to resume. + * @return The response for the pending upload request. + */ + public PendingUploadResponse resumePendingUpload(String name, String version, String pendingUploadType, String connectionName, String pendingUploadId) { + /* + Combined Methods: pendingUpload(String, String, PendingUploadRequest) + Reason: Streamlines the workflow for resuming an upload by allowing all relevant parameters to be set in a single call, + removing the need for manual request object construction and reducing boilerplate. + */ + PendingUploadRequest request = new PendingUploadRequest() + .setPendingUploadType(pendingUploadType) + .setConnectionName(connectionName) + .setPendingUploadId(pendingUploadId); + return pendingUpload(name, version, request); + }/** + * Creates or updates a dataset version from a single file or a folder, automatically detecting the input type. + *

+ * If the provided path is a file, creates a FileDatasetVersion. If it is a directory, creates a FolderDatasetVersion. + *

+ * * @param name The name of the dataset resource. - * @param version The version id of the DatasetVersion to create or update. + * @param version The specific version id of the DatasetVersion to create or replace. + * @param path The path to the file or folder to upload. + * @return The created dataset version, as FileDatasetVersion or FolderDatasetVersion. + * @throws IllegalArgumentException If the provided path is neither a file nor a directory. + * @throws IOException If an I/O error occurs during folder upload. + */ + public Object createDatasetAuto(String name, String version, Path path) throws IOException { + /* + Combined Methods: createDatasetWithFile, createDatasetWithFolder + Reason: Developers often want to create a dataset from a local path, regardless of whether it's a file or folder. + This wrapper abstracts the manual type-checking and method selection, streamlining the workflow and reducing boilerplate. + */ + if (Files.isRegularFile(path)) { + return createDatasetWithFile(name, version, path); + } else if (Files.isDirectory(path)) { + return createDatasetWithFolder(name, version, path); + } else { + throw new IllegalArgumentException("The provided path is neither a file nor a directory: " + path); + } + } + + /** + * Creates or updates a dataset version from a folder, uploading all files recursively, with optional file filter. + *

+ * This overload allows specifying a filter to include only certain files in the upload. + *

+ * + * @param name The name of the dataset resource. + * @param version The specific version id of the DatasetVersion to create or replace. * @param folderPath The path to the folder containing files to upload. - * @return The created or updated FolderDatasetVersion. + * @param fileFilter A filter to select which files to include (e.g., by extension or name). + * @return The created FolderDatasetVersion. * @throws IllegalArgumentException If the provided path is not a directory. - * @throws IOException if an I/O error occurs when accessing the files. + * @throws IOException If an I/O error occurs during folder upload. */ - public FolderDatasetVersion uploadFolderAsDatasetVersion(String name, String version, Path folderPath) throws IOException { + public FolderDatasetVersion createDatasetWithFolder(String name, String version, Path folderPath, java.util.function.Predicate fileFilter) throws IOException { /* - Combined Methods: pendingUpload, BlobClient.upload (per file), createOrUpdateDatasetVersionWithResponse - Reason: This wrapper automates the multi-step workflow of uploading a folder as a dataset version, including obtaining upload credentials, uploading all files, and registering the dataset version. It encapsulates a common, but otherwise complex, developer task into a single, intention-revealing method. + Combined Methods: createDatasetWithFolder (customized) + Reason: Developers often want to upload only a subset of files from a folder (e.g., only .csv files). + This wrapper provides a convenient way to filter files, reducing repetitive code for file selection. */ if (!Files.isDirectory(folderPath)) { - throw logger.logExceptionAsError(new IllegalArgumentException("The provided path is not a folder: " + folderPath)); + throw new IllegalArgumentException("The provided path is not a folder: " + folderPath); } PendingUploadRequest request = new PendingUploadRequest(); PendingUploadResponse pendingUploadResponse = this.pendingUpload(name, version, request); String blobContainerUri = pendingUploadResponse.getBlobReference().getBlobUri(); SasCredential credential = pendingUploadResponse.getBlobReference().getCredential(); String containerUrl = blobContainerUri.substring(0, blobContainerUri.lastIndexOf('/')); - Files.walk(folderPath).filter(Files::isRegularFile).forEach(filePath -> { - String relativePath = folderPath.relativize(filePath).toString().replace('\\', '/'); - BlobClient blobClient = new BlobClientBuilder().endpoint(credential.getSasUri()).blobName(relativePath).buildClient(); - blobClient.upload(BinaryData.fromFile(filePath), true); - }); + Files.walk(folderPath) + .filter(Files::isRegularFile) + .filter(fileFilter) + .forEach(filePath -> { + String relativePath = folderPath.relativize(filePath).toString().replace('\\', '/'); + BlobClient blobClient = new BlobClientBuilder().endpoint(credential.getSasUri()).blobName(relativePath).buildClient(); + blobClient.upload(BinaryData.fromFile(filePath), true); + }); RequestOptions requestOptions = new RequestOptions(); FolderDatasetVersion datasetVersion = this .createOrUpdateDatasetVersionWithResponse(name, version, @@ -626,43 +814,257 @@ public FolderDatasetVersion uploadFolderAsDatasetVersion(String name, String ver } /** - * Deletes all versions of a Dataset by name. - * + * Creates or updates a dataset version from a file, using sensible defaults for request options. + *

+ * Simplifies the creation of a FileDatasetVersion by requiring only the essential parameters. + *

+ * * @param name The name of the dataset resource. + * @param version The specific version id of the DatasetVersion to create or replace. + * @param filePath The path to the file to upload. + * @return The created FileDatasetVersion. + * @throws IllegalArgumentException If the provided path is not a file. */ - public void deleteAllDatasetVersions(String name) { + public FileDatasetVersion createDatasetWithFile(String name, String version, Path filePath) { /* - Combined Methods: listDatasetVersions, deleteDatasetVersion - Reason: This wrapper enables a common bulk operation—deleting all versions of a dataset—by internally listing all versions and deleting each one. It saves developers from writing repetitive code and ensures correct sequencing. + Wrapped Method: createDatasetWithFile + Reason: This method already provides a high-level abstraction, but is included here for completeness and discoverability, + ensuring developers can easily find the streamlined file upload path without needing to construct request options. */ - for (DatasetVersion version : listDatasetVersions(name)) { - deleteDatasetVersion(name, version.getVersion()); + return createDatasetWithFile(name, version, filePath); + }/** + * Deletes a specific version of a dataset, handling common error scenarios and optionally suppressing 404 errors. + * + * @param name The name of the dataset. + * @param version The version of the dataset to delete. + * @param suppressNotFound If true, suppresses ResourceNotFoundException (404) and returns silently if the version does not exist. + * @throws IllegalArgumentException if parameters fail validation. + * @throws HttpResponseException if the request is rejected by server (other than 404, if suppressed). + * @throws ClientAuthenticationException if the request is rejected by server on status code 401. + * @throws ResourceModifiedException if the request is rejected by server on status code 409. + * @throws RuntimeException for all other wrapped checked exceptions if the request fails to be sent. + */ + public void deleteDatasetVersionIfExists(String name, String version, boolean suppressNotFound) { + /* + Combined Methods: deleteDatasetVersion, deleteDatasetVersionWithResponse + Reason: Developers often want to delete a resource if it exists, but not treat a missing resource (404) as an error. + This wrapper streamlines the common pattern of catching and suppressing ResourceNotFoundException, reducing boilerplate. + */ + try { + deleteDatasetVersion(name, version); + } catch (ResourceNotFoundException ex) { + if (!suppressNotFound) { + throw ex; + } + // else: silently ignore 404 } } /** - * Retrieves the latest version of a Dataset by name. + * Deletes a specific version of a dataset, allowing the caller to specify custom request options. * - * @param name The name of the dataset resource. - * @return The latest DatasetVersion, or null if none exist. + * @param name The name of the dataset. + * @param version The version of the dataset to delete. + * @param requestOptions The options to configure the HTTP request before sending. + * @throws IllegalArgumentException if parameters fail validation. + * @throws HttpResponseException if the request is rejected by server. + * @throws ClientAuthenticationException if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException if the request is rejected by server on status code 404. + * @throws ResourceModifiedException if the request is rejected by server on status code 409. + * @throws RuntimeException for all other wrapped checked exceptions if the request fails to be sent. */ - public DatasetVersion getLatestDatasetVersion(String name) { + public void deleteDatasetVersion(String name, String version, RequestOptions requestOptions) { /* - Combined Methods: listDatasetVersions, getDatasetVersion - Reason: This wrapper expresses the intent to fetch the latest version of a dataset, hiding the need to manually enumerate and select the latest version. It streamlines a frequent lookup pattern. + Combined Methods: deleteDatasetVersionWithResponse + Reason: The codegen only exposes deleteDatasetVersionWithResponse for custom RequestOptions, but developers expect + a void-returning convenience overload for simple use cases. This wrapper provides a streamlined, idiomatic overload. */ - DatasetVersion latest = null; - for (DatasetVersion version : listDatasetVersions(name)) { - if (latest == null || version.getVersion().compareTo(latest.getVersion()) > 0) { - latest = version; - } + deleteDatasetVersionWithResponse(name, version, requestOptions); + }/** + * Creates or updates a DatasetVersion with minimal required parameters, using sensible defaults for optional fields. + *

+ * This wrapper streamlines the creation or update of a DatasetVersion by requiring only the most essential parameters, + * and automatically constructing the DatasetVersion model with optional fields left unset. This is ideal for the + * common case where only name, version, type, and dataUri are needed. + *

+ * + * @param name The name of the Dataset resource. + * @param version The version identifier for the DatasetVersion. + * @param type The type of the DatasetVersion (e.g., "uri_file" or "uri_folder"). + * @param dataUri The URI to the data (required on create). + * @return The created or updated DatasetVersion. + */ + public DatasetVersion createOrUpdateDatasetVersion(String name, String version, String type, String dataUri) { + /* + Combined Methods: createOrUpdateDatasetVersion(String, String, DatasetVersion) + Reason: Developers often only need to specify the minimal required fields for a DatasetVersion. This wrapper reduces boilerplate by constructing the DatasetVersion model internally, applying sensible defaults for optional fields, and invoking the existing convenience method. This aligns with the options pattern and streamlines the most common workflow. + */ + DatasetVersion datasetVersion = new DatasetVersion() + .setName(name) + .setVersion(version) + .setType(type) + .setDataUri(dataUri); + return createOrUpdateDatasetVersion(name, version, datasetVersion); + } + + /** + * Creates or updates a DatasetVersion with required and commonly-used optional parameters, simplifying model construction. + *

+ * This wrapper allows developers to specify the most frequently-used fields directly, including description and tags, + * without manually constructing a DatasetVersion object. It is intended for scenarios where developers want to + * supply metadata along with the required fields. + *

+ * + * @param name The name of the Dataset resource. + * @param version The version identifier for the DatasetVersion. + * @param type The type of the DatasetVersion (e.g., "uri_file" or "uri_folder"). + * @param dataUri The URI to the data (required on create). + * @param description The description of the DatasetVersion. + * @param tags The tags to associate with the DatasetVersion. + * @return The created or updated DatasetVersion. + */ + public DatasetVersion createOrUpdateDatasetVersion( + String name, + String version, + String type, + String dataUri, + String description, + Map tags + ) { + /* + Combined Methods: createOrUpdateDatasetVersion(String, String, DatasetVersion) + Reason: This wrapper targets the common workflow of creating or updating a DatasetVersion with both required and frequently-used optional fields, reducing the need for verbose model construction and improving clarity. + */ + DatasetVersion datasetVersion = new DatasetVersion() + .setName(name) + .setVersion(version) + .setType(type) + .setDataUri(dataUri) + .setDescription(description) + .setTags(tags); + return createOrUpdateDatasetVersion(name, version, datasetVersion); + } + + /** + * Creates or updates a DatasetVersion with all available parameters, providing a single entry point for full customization. + *

+ * This wrapper enables developers to specify every possible field of a DatasetVersion directly, reducing the need to + * manually instantiate and populate the model. It is intended for advanced scenarios where all fields may be relevant. + *

+ * + * @param name The name of the Dataset resource. + * @param version The version identifier for the DatasetVersion. + * @param type The type of the DatasetVersion (e.g., "uri_file" or "uri_folder"). + * @param dataUri The URI to the data (required on create). + * @param isReference Whether this DatasetVersion is a reference. + * @param connectionName The name of the connection. + * @param id The unique identifier of the DatasetVersion. + * @param description The description of the DatasetVersion. + * @param tags The tags to associate with the DatasetVersion. + * @return The created or updated DatasetVersion. + */ + public DatasetVersion createOrUpdateDatasetVersion( + String name, + String version, + String type, + String dataUri, + Boolean isReference, + String connectionName, + String id, + String description, + Map tags + ) { + /* + Combined Methods: createOrUpdateDatasetVersion(String, String, DatasetVersion) + Reason: This wrapper provides a comprehensive overload for advanced scenarios, enabling full control over all DatasetVersion fields without requiring manual model construction. This reduces repetitive code and aligns with the options pattern for complex inputs. + */ + DatasetVersion datasetVersion = new DatasetVersion() + .setName(name) + .setVersion(version) + .setType(type) + .setDataUri(dataUri) + .setIsReference(isReference) + .setConnectionName(connectionName) + .setId(id) + .setDescription(description) + .setTags(tags); + return createOrUpdateDatasetVersion(name, version, datasetVersion); + }/** + * Retrieves the SAS URI for the blob associated with a Dataset version, simplifying access for download or upload scenarios. + *

+ * This method abstracts away the details of the credential response structure and returns the direct SAS URI string, + * which is the most common developer need for accessing the blob. + *

+ * + * @param name The name of the Dataset resource. + * @param version The specific version id of the DatasetVersion to operate on. + * @return The SAS URI string for the blob associated with the Dataset version. + * @throws IllegalArgumentException if parameters fail validation. + * @throws HttpResponseException if the request is rejected by server. + * @throws ClientAuthenticationException if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException if the request is rejected by server on status code 404. + * @throws ResourceModifiedException if the request is rejected by server on status code 409. + * @throws RuntimeException for all other wrapped checked exceptions if the request fails to be sent. + */ + public String getDatasetVersionBlobSasUri(String name, String version) { + /* + Combined Methods: getCredentials(String, String) + Reason: Developers commonly want to access the blob directly (e.g., for download/upload) and need only the SAS URI. + This wrapper extracts the SAS URI from the nested response, eliminating the need for the user to parse the result structure. + */ + AssetCredentialResult result = getCredentials(name, version); + if (result == null + || result.getBlobReference() == null + || result.getBlobReference().getCredential() == null + || result.getBlobReference().getCredential().getSasUri() == null) { + throw new IllegalStateException("SAS URI not found in the credential response."); } - if (latest == null) { - return null; + return result.getBlobReference().getCredential().getSasUri(); + } + + /** + * Retrieves the full Blob URI (including SAS token) for the blob associated with a Dataset version. + *

+ * This method combines the blobUri and the SAS token, providing a ready-to-use URI for direct blob access. + *

+ * + * @param name The name of the Dataset resource. + * @param version The specific version id of the DatasetVersion to operate on. + * @return The full Blob URI (including SAS token) for the Dataset version. + * @throws IllegalArgumentException if parameters fail validation. + * @throws HttpResponseException if the request is rejected by server. + * @throws ClientAuthenticationException if the request is rejected by server on status code 401. + * @throws ResourceNotFoundException if the request is rejected by server on status code 404. + * @throws ResourceModifiedException if the request is rejected by server on status code 409. + * @throws RuntimeException for all other wrapped checked exceptions if the request fails to be sent. + */ + public String getDatasetVersionBlobUriWithSas(String name, String version) { + /* + Combined Methods: getCredentials(String, String) + Reason: Developers often need a single URI for direct blob access (e.g., with Azure Storage SDKs or tools). + This wrapper combines the blobUri and the SAS token, hiding response parsing and URI construction logic. + */ + AssetCredentialResult result = getCredentials(name, version); + if (result == null + || result.getBlobReference() == null + || result.getBlobReference().getBlobUri() == null + || result.getBlobReference().getCredential() == null + || result.getBlobReference().getCredential().getSasUri() == null) { + throw new IllegalStateException("Blob URI or SAS token not found in the credential response."); + } + String blobUri = result.getBlobReference().getBlobUri(); + String sasUri = result.getBlobReference().getCredential().getSasUri(); + // If the SAS token is already appended, return as is; otherwise, combine. + if (blobUri.contains("?")) { + return blobUri; + } + // Assume sasUri is of the form "?sv=..."; append to blobUri if not present. + if (sasUri.startsWith("?")) { + return blobUri + sasUri; } - return getDatasetVersion(name, latest.getVersion()); + return blobUri + "?" + sasUri; } /********************* END OF GENERATED CODE *********************/ -} +} \ No newline at end of file