This is an automated email from the ASF dual-hosted git repository.

tison pushed a commit to branch generate-java-configs
in repository https://gitbox.apache.org/repos/asf/opendal.git

commit f90d63636295ef90bfd52cecbb0ee28e0b03418b
Author: tison <[email protected]>
AuthorDate: Fri Jan 3 18:27:27 2025 +0800

    impl
    
    Signed-off-by: tison <[email protected]>
---
 .../java/org/apache/opendal/ServiceConfig.java     | 3572 ++++++++++++++++++++
 dev/src/generate/java.j2                           |   10 +-
 dev/src/generate/java.rs                           |   87 +-
 3 files changed, 3636 insertions(+), 33 deletions(-)

diff --git a/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java 
b/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java
new file mode 100644
index 000000000..27dabdc72
--- /dev/null
+++ b/bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java
@@ -0,0 +1,3572 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// DO NOT EDIT IT MANUALLY. This file is generated by 
opendal/dev/generate/java.rs.
+
+package org.apache.opendal;
+
+import java.time.Duration;
+import java.util.HashMap;
+import lombok.AccessLevel;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Service configurations that are mapped from
+ * <a 
href="https://docs.rs/opendal/latest/opendal/services/index.html>OpenDAL's 
services</a>.
+ */
+@SuppressWarnings("unused") // intended to be used by users
+public interface ServiceConfig {
+    String scheme();
+
+    HashMap<String, String> configMap();
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class AliyunDrive implements ServiceConfig {
+        /**
+         * The drive_type of this backend.
+         * <p>
+         * All operations will happen under this type of drive.
+         * <p>
+         * Available values are `default`, `backup` and `resource`.
+         * <p>
+         * Fallback to default if not set or no other drives can be found.
+         */
+        private final @NonNull String driveType;
+        /**
+         * The Root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         * <p>
+         * Default to `/` if not set.
+         */
+        private final String root;
+        /**
+         * The access_token of this backend.
+         * <p>
+         * Solution for client-only purpose. #4733
+         * <p>
+         * Required if no client_id, client_secret and refresh_token are 
provided.
+         */
+        private final String accessToken;
+        /**
+         * The client_id of this backend.
+         * <p>
+         * Required if no access_token is provided.
+         */
+        private final String clientId;
+        /**
+         * The client_secret of this backend.
+         * <p>
+         * Required if no access_token is provided.
+         */
+        private final String clientSecret;
+        /**
+         * The refresh_token of this backend.
+         * <p>
+         * Required if no access_token is provided.
+         */
+        private final String refreshToken;
+
+        @Override
+        public String scheme() {
+            return "aliyun_drive";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("drive_type", driveType);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (accessToken != null) {
+                map.put("access_token", accessToken);
+            }
+            if (clientId != null) {
+                map.put("client_id", clientId);
+            }
+            if (clientSecret != null) {
+                map.put("client_secret", clientSecret);
+            }
+            if (refreshToken != null) {
+                map.put("refresh_token", refreshToken);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Alluxio implements ServiceConfig {
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         * <p>
+         * default to `/` if not set.
+         */
+        private final String root;
+        /**
+         * endpoint of this backend.
+         * <p>
+         * Endpoint must be full uri, mostly like `http://127.0.0.1:39999`.
+         */
+        private final String endpoint;
+
+        @Override
+        public String scheme() {
+            return "alluxio";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Atomicserver implements ServiceConfig {
+        /**
+         * work dir of this backend
+         */
+        private final String root;
+        /**
+         * endpoint of this backend
+         */
+        private final String endpoint;
+        /**
+         * private_key of this backend
+         */
+        private final String privateKey;
+        /**
+         * public_key of this backend
+         */
+        private final String publicKey;
+        /**
+         * parent_resource_id of this backend
+         */
+        private final String parentResourceId;
+
+        @Override
+        public String scheme() {
+            return "atomicserver";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (privateKey != null) {
+                map.put("private_key", privateKey);
+            }
+            if (publicKey != null) {
+                map.put("public_key", publicKey);
+            }
+            if (parentResourceId != null) {
+                map.put("parent_resource_id", parentResourceId);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Azblob implements ServiceConfig {
+        /**
+         * The container name of Azblob service backend.
+         */
+        private final @NonNull String container;
+        /**
+         * The root of Azblob service backend.
+         * <p>
+         * All operations will happen under this root.
+         */
+        private final String root;
+        /**
+         * The endpoint of Azblob service backend.
+         * <p>
+         * Endpoint must be full uri, e.g.
+         * <p>
+         * - Azblob: `https://accountname.blob.core.windows.net`
+         * - Azurite: `http://127.0.0.1:10000/devstoreaccount1`
+         */
+        private final String endpoint;
+        /**
+         * The account name of Azblob service backend.
+         */
+        private final String accountName;
+        /**
+         * The account key of Azblob service backend.
+         */
+        private final String accountKey;
+        /**
+         * The encryption key of Azblob service backend.
+         */
+        private final String encryptionKey;
+        /**
+         * The encryption key sha256 of Azblob service backend.
+         */
+        private final String encryptionKeySha256;
+        /**
+         * The encryption algorithm of Azblob service backend.
+         */
+        private final String encryptionAlgorithm;
+        /**
+         * The sas token of Azblob service backend.
+         */
+        private final String sasToken;
+        /**
+         * The maximum batch operations of Azblob service backend.
+         */
+        private final Long batchMaxOperations;
+
+        @Override
+        public String scheme() {
+            return "azblob";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("container", container);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (accountName != null) {
+                map.put("account_name", accountName);
+            }
+            if (accountKey != null) {
+                map.put("account_key", accountKey);
+            }
+            if (encryptionKey != null) {
+                map.put("encryption_key", encryptionKey);
+            }
+            if (encryptionKeySha256 != null) {
+                map.put("encryption_key_sha256", encryptionKeySha256);
+            }
+            if (encryptionAlgorithm != null) {
+                map.put("encryption_algorithm", encryptionAlgorithm);
+            }
+            if (sasToken != null) {
+                map.put("sas_token", sasToken);
+            }
+            if (batchMaxOperations != null) {
+                map.put("batch_max_operations", 
String.valueOf(batchMaxOperations));
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Azdls implements ServiceConfig {
+        /**
+         * Filesystem name of this backend.
+         */
+        private final @NonNull String filesystem;
+        /**
+         * Root of this backend.
+         */
+        private final String root;
+        /**
+         * Endpoint of this backend.
+         */
+        private final String endpoint;
+        /**
+         * Account name of this backend.
+         */
+        private final String accountName;
+        /**
+         * Account key of this backend.
+         */
+        private final String accountKey;
+
+        @Override
+        public String scheme() {
+            return "azdls";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("filesystem", filesystem);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (accountName != null) {
+                map.put("account_name", accountName);
+            }
+            if (accountKey != null) {
+                map.put("account_key", accountKey);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Azfile implements ServiceConfig {
+        /**
+         * The share name for azfile.
+         */
+        private final @NonNull String shareName;
+        /**
+         * The root path for azfile.
+         */
+        private final String root;
+        /**
+         * The endpoint for azfile.
+         */
+        private final String endpoint;
+        /**
+         * The account name for azfile.
+         */
+        private final String accountName;
+        /**
+         * The account key for azfile.
+         */
+        private final String accountKey;
+        /**
+         * The sas token for azfile.
+         */
+        private final String sasToken;
+
+        @Override
+        public String scheme() {
+            return "azfile";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("share_name", shareName);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (accountName != null) {
+                map.put("account_name", accountName);
+            }
+            if (accountKey != null) {
+                map.put("account_key", accountKey);
+            }
+            if (sasToken != null) {
+                map.put("sas_token", sasToken);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class B2 implements ServiceConfig {
+        /**
+         * bucket of this backend.
+         * <p>
+         * required.
+         */
+        private final @NonNull String bucket;
+        /**
+         * bucket id of this backend.
+         * <p>
+         * required.
+         */
+        private final @NonNull String bucketId;
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         */
+        private final String root;
+        /**
+         * keyID of this backend.
+         * <p>
+         * - If application_key_id is set, we will take user's input first.
+         * - If not, we will try to load it from environment.
+         */
+        private final String applicationKeyId;
+        /**
+         * applicationKey of this backend.
+         * <p>
+         * - If application_key is set, we will take user's input first.
+         * - If not, we will try to load it from environment.
+         */
+        private final String applicationKey;
+
+        @Override
+        public String scheme() {
+            return "b2";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("bucket", bucket);
+            map.put("bucket_id", bucketId);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (applicationKeyId != null) {
+                map.put("application_key_id", applicationKeyId);
+            }
+            if (applicationKey != null) {
+                map.put("application_key", applicationKey);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Cacache implements ServiceConfig {
+        /**
+         * That path to the cacache data directory.
+         */
+        private final String datadir;
+
+        @Override
+        public String scheme() {
+            return "cacache";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (datadir != null) {
+                map.put("datadir", datadir);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Chainsafe implements ServiceConfig {
+        /**
+         * bucket_id of this backend.
+         * <p>
+         * required.
+         */
+        private final @NonNull String bucketId;
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         */
+        private final String root;
+        /**
+         * api_key of this backend.
+         */
+        private final String apiKey;
+
+        @Override
+        public String scheme() {
+            return "chainsafe";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("bucket_id", bucketId);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (apiKey != null) {
+                map.put("api_key", apiKey);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class CloudflareKv implements ServiceConfig {
+        /**
+         * The token used to authenticate with CloudFlare.
+         */
+        private final String token;
+        /**
+         * The account ID used to authenticate with CloudFlare. Used as URI 
path parameter.
+         */
+        private final String accountId;
+        /**
+         * The namespace ID. Used as URI path parameter.
+         */
+        private final String namespaceId;
+        /**
+         * Root within this backend.
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "cloudflare_kv";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (token != null) {
+                map.put("token", token);
+            }
+            if (accountId != null) {
+                map.put("account_id", accountId);
+            }
+            if (namespaceId != null) {
+                map.put("namespace_id", namespaceId);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Compfs implements ServiceConfig {
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "compfs";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Cos implements ServiceConfig {
+        /**
+         * Root of this backend.
+         */
+        private final String root;
+        /**
+         * Endpoint of this backend.
+         */
+        private final String endpoint;
+        /**
+         * Secret ID of this backend.
+         */
+        private final String secretId;
+        /**
+         * Secret key of this backend.
+         */
+        private final String secretKey;
+        /**
+         * Bucket of this backend.
+         */
+        private final String bucket;
+        /**
+         * Disable config load so that opendal will not load config from
+         */
+        private final Boolean disableConfigLoad;
+
+        @Override
+        public String scheme() {
+            return "cos";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (secretId != null) {
+                map.put("secret_id", secretId);
+            }
+            if (secretKey != null) {
+                map.put("secret_key", secretKey);
+            }
+            if (bucket != null) {
+                map.put("bucket", bucket);
+            }
+            if (disableConfigLoad != null) {
+                map.put("disable_config_load", 
String.valueOf(disableConfigLoad));
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class D1 implements ServiceConfig {
+        /**
+         * Set the token of cloudflare api.
+         */
+        private final String token;
+        /**
+         * Set the account id of cloudflare api.
+         */
+        private final String accountId;
+        /**
+         * Set the database id of cloudflare api.
+         */
+        private final String databaseId;
+        /**
+         * Set the working directory of OpenDAL.
+         */
+        private final String root;
+        /**
+         * Set the table of D1 Database.
+         */
+        private final String table;
+        /**
+         * Set the key field of D1 Database.
+         */
+        private final String keyField;
+        /**
+         * Set the value field of D1 Database.
+         */
+        private final String valueField;
+
+        @Override
+        public String scheme() {
+            return "d1";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (token != null) {
+                map.put("token", token);
+            }
+            if (accountId != null) {
+                map.put("account_id", accountId);
+            }
+            if (databaseId != null) {
+                map.put("database_id", databaseId);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (table != null) {
+                map.put("table", table);
+            }
+            if (keyField != null) {
+                map.put("key_field", keyField);
+            }
+            if (valueField != null) {
+                map.put("value_field", valueField);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Dashmap implements ServiceConfig {
+        /**
+         * The root path for dashmap.
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "dashmap";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Dbfs implements ServiceConfig {
+        /**
+         * The root for dbfs.
+         */
+        private final String root;
+        /**
+         * The endpoint for dbfs.
+         */
+        private final String endpoint;
+        /**
+         * The token for dbfs.
+         */
+        private final String token;
+
+        @Override
+        public String scheme() {
+            return "dbfs";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (token != null) {
+                map.put("token", token);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Dropbox implements ServiceConfig {
+        /**
+         * root path for dropbox.
+         */
+        private final String root;
+        /**
+         * access token for dropbox.
+         */
+        private final String accessToken;
+        /**
+         * refresh_token for dropbox.
+         */
+        private final String refreshToken;
+        /**
+         * client_id for dropbox.
+         */
+        private final String clientId;
+        /**
+         * client_secret for dropbox.
+         */
+        private final String clientSecret;
+
+        @Override
+        public String scheme() {
+            return "dropbox";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (accessToken != null) {
+                map.put("access_token", accessToken);
+            }
+            if (refreshToken != null) {
+                map.put("refresh_token", refreshToken);
+            }
+            if (clientId != null) {
+                map.put("client_id", clientId);
+            }
+            if (clientSecret != null) {
+                map.put("client_secret", clientSecret);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Etcd implements ServiceConfig {
+        /**
+         * network address of the Etcd services.
+         * If use https, must set TLS options: `ca_path`, `cert_path`, 
`key_path`.
+         * e.g. "127.0.0.1:23790,127.0.0.1:23791,127.0.0.1:23792" or 
"http://127.0.0.1:23790,http://127.0.0.1:23791,http://127.0.0.1:23792"; or 
"https://127.0.0.1:23790,https://127.0.0.1:23791,https://127.0.0.1:23792";
+         * <p>
+         * default is "http://127.0.0.1:2379";
+         */
+        private final String endpoints;
+        /**
+         * the username to connect etcd service.
+         * <p>
+         * default is None
+         */
+        private final String username;
+        /**
+         * the password for authentication
+         * <p>
+         * default is None
+         */
+        private final String password;
+        /**
+         * the working directory of the etcd service. Can be "/path/to/dir"
+         * <p>
+         * default is "/"
+         */
+        private final String root;
+        /**
+         * certificate authority file path
+         * <p>
+         * default is None
+         */
+        private final String caPath;
+        /**
+         * cert path
+         * <p>
+         * default is None
+         */
+        private final String certPath;
+        /**
+         * key path
+         * <p>
+         * default is None
+         */
+        private final String keyPath;
+
+        @Override
+        public String scheme() {
+            return "etcd";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (endpoints != null) {
+                map.put("endpoints", endpoints);
+            }
+            if (username != null) {
+                map.put("username", username);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (caPath != null) {
+                map.put("ca_path", caPath);
+            }
+            if (certPath != null) {
+                map.put("cert_path", certPath);
+            }
+            if (keyPath != null) {
+                map.put("key_path", keyPath);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Fs implements ServiceConfig {
+        /**
+         * root dir for backend
+         */
+        private final String root;
+        /**
+         * tmp dir for atomic write
+         */
+        private final String atomicWriteDir;
+
+        @Override
+        public String scheme() {
+            return "fs";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (atomicWriteDir != null) {
+                map.put("atomic_write_dir", atomicWriteDir);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Gcs implements ServiceConfig {
+        /**
+         * bucket name
+         */
+        private final @NonNull String bucket;
+        /**
+         * root URI, all operations happens under `root`
+         */
+        private final String root;
+        /**
+         * endpoint URI of GCS service,
+         * default is `https://storage.googleapis.com`
+         */
+        private final String endpoint;
+        /**
+         * Scope for gcs.
+         */
+        private final String scope;
+        /**
+         * Service Account for gcs.
+         */
+        private final String serviceAccount;
+        /**
+         * Credentials string for GCS service OAuth2 authentication.
+         */
+        private final String credential;
+        /**
+         * Local path to credentials file for GCS service OAuth2 
authentication.
+         */
+        private final String credentialPath;
+        /**
+         * The predefined acl for GCS.
+         */
+        private final String predefinedAcl;
+        /**
+         * The default storage class used by gcs.
+         */
+        private final String defaultStorageClass;
+        /**
+         * Allow opendal to send requests without signing when credentials are 
not
+         * loaded.
+         */
+        private final Boolean allowAnonymous;
+        /**
+         * Disable attempting to load credentials from the GCE metadata server 
when
+         * running within Google Cloud.
+         */
+        private final Boolean disableVmMetadata;
+        /**
+         * Disable loading configuration from the environment.
+         */
+        private final Boolean disableConfigLoad;
+        /**
+         * A Google Cloud OAuth2 token.
+         * <p>
+         * Takes precedence over `credential` and `credential_path`.
+         */
+        private final String token;
+
+        @Override
+        public String scheme() {
+            return "gcs";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("bucket", bucket);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (scope != null) {
+                map.put("scope", scope);
+            }
+            if (serviceAccount != null) {
+                map.put("service_account", serviceAccount);
+            }
+            if (credential != null) {
+                map.put("credential", credential);
+            }
+            if (credentialPath != null) {
+                map.put("credential_path", credentialPath);
+            }
+            if (predefinedAcl != null) {
+                map.put("predefined_acl", predefinedAcl);
+            }
+            if (defaultStorageClass != null) {
+                map.put("default_storage_class", defaultStorageClass);
+            }
+            if (allowAnonymous != null) {
+                map.put("allow_anonymous", String.valueOf(allowAnonymous));
+            }
+            if (disableVmMetadata != null) {
+                map.put("disable_vm_metadata", 
String.valueOf(disableVmMetadata));
+            }
+            if (disableConfigLoad != null) {
+                map.put("disable_config_load", 
String.valueOf(disableConfigLoad));
+            }
+            if (token != null) {
+                map.put("token", token);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Gdrive implements ServiceConfig {
+        /**
+         * The root for gdrive
+         */
+        private final String root;
+        /**
+         * Access token for gdrive.
+         */
+        private final String accessToken;
+        /**
+         * Refresh token for gdrive.
+         */
+        private final String refreshToken;
+        /**
+         * Client id for gdrive.
+         */
+        private final String clientId;
+        /**
+         * Client secret for gdrive.
+         */
+        private final String clientSecret;
+
+        @Override
+        public String scheme() {
+            return "gdrive";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (accessToken != null) {
+                map.put("access_token", accessToken);
+            }
+            if (refreshToken != null) {
+                map.put("refresh_token", refreshToken);
+            }
+            if (clientId != null) {
+                map.put("client_id", clientId);
+            }
+            if (clientSecret != null) {
+                map.put("client_secret", clientSecret);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Ghac implements ServiceConfig {
+        /**
+         * The root path for ghac.
+         */
+        private final String root;
+        /**
+         * The version that used by cache.
+         */
+        private final String version;
+        /**
+         * The endpoint for ghac service.
+         */
+        private final String endpoint;
+        /**
+         * The runtime token for ghac service.
+         */
+        private final String runtimeToken;
+
+        @Override
+        public String scheme() {
+            return "ghac";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (version != null) {
+                map.put("version", version);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (runtimeToken != null) {
+                map.put("runtime_token", runtimeToken);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Github implements ServiceConfig {
+        /**
+         * GitHub repo owner.
+         * <p>
+         * required.
+         */
+        private final @NonNull String owner;
+        /**
+         * GitHub repo name.
+         * <p>
+         * required.
+         */
+        private final @NonNull String repo;
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         */
+        private final String root;
+        /**
+         * GitHub access_token.
+         * <p>
+         * optional.
+         * If not provided, the backend will only support read operations for 
public repositories.
+         * And rate limit will be limited to 60 requests per hour.
+         */
+        private final String token;
+
+        @Override
+        public String scheme() {
+            return "github";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("owner", owner);
+            map.put("repo", repo);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (token != null) {
+                map.put("token", token);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Gridfs implements ServiceConfig {
+        /**
+         * The connection string of the MongoDB service.
+         */
+        private final String connectionString;
+        /**
+         * The database name of the MongoDB GridFs service to read/write.
+         */
+        private final String database;
+        /**
+         * The bucket name of the MongoDB GridFs service to read/write.
+         */
+        private final String bucket;
+        /**
+         * The chunk size of the MongoDB GridFs service used to break the user 
file into chunks.
+         */
+        private final Integer chunkSize;
+        /**
+         * The working directory, all operations will be performed under it.
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "gridfs";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (connectionString != null) {
+                map.put("connection_string", connectionString);
+            }
+            if (database != null) {
+                map.put("database", database);
+            }
+            if (bucket != null) {
+                map.put("bucket", bucket);
+            }
+            if (chunkSize != null) {
+                map.put("chunk_size", String.valueOf(chunkSize));
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class HdfsNative implements ServiceConfig {
+        /**
+         * work dir of this backend
+         */
+        private final String root;
+        /**
+         * url of this backend
+         */
+        private final String url;
+        /**
+         * enable the append capacity
+         */
+        private final Boolean enableAppend;
+
+        @Override
+        public String scheme() {
+            return "hdfs_native";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (url != null) {
+                map.put("url", url);
+            }
+            if (enableAppend != null) {
+                map.put("enable_append", String.valueOf(enableAppend));
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Http implements ServiceConfig {
+        /**
+         * endpoint of this backend
+         */
+        private final String endpoint;
+        /**
+         * username of this backend
+         */
+        private final String username;
+        /**
+         * password of this backend
+         */
+        private final String password;
+        /**
+         * token of this backend
+         */
+        private final String token;
+        /**
+         * root of this backend
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "http";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (username != null) {
+                map.put("username", username);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            if (token != null) {
+                map.put("token", token);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Huggingface implements ServiceConfig {
+        /**
+         * Repo type of this backend. Default is model.
+         * <p>
+         * Available values:
+         * - model
+         * - dataset
+         */
+        private final String repoType;
+        /**
+         * Repo id of this backend.
+         * <p>
+         * This is required.
+         */
+        private final String repoId;
+        /**
+         * Revision of this backend.
+         * <p>
+         * Default is main.
+         */
+        private final String revision;
+        /**
+         * Root of this backend. Can be "/path/to/dir".
+         * <p>
+         * Default is "/".
+         */
+        private final String root;
+        /**
+         * Token of this backend.
+         * <p>
+         * This is optional.
+         */
+        private final String token;
+
+        @Override
+        public String scheme() {
+            return "huggingface";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (repoType != null) {
+                map.put("repo_type", repoType);
+            }
+            if (repoId != null) {
+                map.put("repo_id", repoId);
+            }
+            if (revision != null) {
+                map.put("revision", revision);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (token != null) {
+                map.put("token", token);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Icloud implements ServiceConfig {
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         * <p>
+         * default to `/` if not set.
+         */
+        private final String root;
+        /**
+         * apple_id of this backend.
+         * <p>
+         * apple_id must be full, mostly like `[email protected]`.
+         */
+        private final String appleId;
+        /**
+         * password of this backend.
+         * <p>
+         * password must be full.
+         */
+        private final String password;
+        /**
+         * Session
+         * <p>
+         * token must be valid.
+         */
+        private final String trustToken;
+        /**
+         * ds_web_auth_token must be set in Session
+         */
+        private final String dsWebAuthToken;
+        /**
+         * enable the china origin
+         * China region `origin` Header needs to be set to 
"https://www.icloud.com.cn";.
+         * <p>
+         * otherwise Apple server will return 302.
+         */
+        private final Boolean isChinaMainland;
+
+        @Override
+        public String scheme() {
+            return "icloud";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (appleId != null) {
+                map.put("apple_id", appleId);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            if (trustToken != null) {
+                map.put("trust_token", trustToken);
+            }
+            if (dsWebAuthToken != null) {
+                map.put("ds_web_auth_token", dsWebAuthToken);
+            }
+            if (isChinaMainland != null) {
+                map.put("is_china_mainland", String.valueOf(isChinaMainland));
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Ipfs implements ServiceConfig {
+        /**
+         * IPFS gateway endpoint.
+         */
+        private final String endpoint;
+        /**
+         * IPFS root.
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "ipfs";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Ipmfs implements ServiceConfig {
+        /**
+         * Root for ipfs.
+         */
+        private final String root;
+        /**
+         * Endpoint for ipfs.
+         */
+        private final String endpoint;
+
+        @Override
+        public String scheme() {
+            return "ipmfs";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Koofr implements ServiceConfig {
+        /**
+         * Koofr endpoint.
+         */
+        private final @NonNull String endpoint;
+        /**
+         * Koofr email.
+         */
+        private final @NonNull String email;
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         */
+        private final String root;
+        /**
+         * password of this backend. (Must be the application password)
+         */
+        private final String password;
+
+        @Override
+        public String scheme() {
+            return "koofr";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("endpoint", endpoint);
+            map.put("email", email);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Lakefs implements ServiceConfig {
+        /**
+         * Base url.
+         * <p>
+         * This is required.
+         */
+        private final String endpoint;
+        /**
+         * Username for Lakefs basic authentication.
+         * <p>
+         * This is required.
+         */
+        private final String username;
+        /**
+         * Password for Lakefs basic authentication.
+         * <p>
+         * This is required.
+         */
+        private final String password;
+        /**
+         * Root of this backend. Can be "/path/to/dir".
+         * <p>
+         * Default is "/".
+         */
+        private final String root;
+        /**
+         * The repository name
+         * <p>
+         * This is required.
+         */
+        private final String repository;
+        /**
+         * Name of the branch or a commit ID. Default is main.
+         * <p>
+         * This is optional.
+         */
+        private final String branch;
+
+        @Override
+        public String scheme() {
+            return "lakefs";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (username != null) {
+                map.put("username", username);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (repository != null) {
+                map.put("repository", repository);
+            }
+            if (branch != null) {
+                map.put("branch", branch);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Libsql implements ServiceConfig {
+        /**
+         * Connection string for libsql service.
+         */
+        private final String connectionString;
+        /**
+         * Authentication token for libsql service.
+         */
+        private final String authToken;
+        /**
+         * Table name for libsql service.
+         */
+        private final String table;
+        /**
+         * Key field name for libsql service.
+         */
+        private final String keyField;
+        /**
+         * Value field name for libsql service.
+         */
+        private final String valueField;
+        /**
+         * Root for libsql service.
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "libsql";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (connectionString != null) {
+                map.put("connection_string", connectionString);
+            }
+            if (authToken != null) {
+                map.put("auth_token", authToken);
+            }
+            if (table != null) {
+                map.put("table", table);
+            }
+            if (keyField != null) {
+                map.put("key_field", keyField);
+            }
+            if (valueField != null) {
+                map.put("value_field", valueField);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Memcached implements ServiceConfig {
+        /**
+         * network address of the memcached service.
+         * <p>
+         * For example: "tcp://localhost:11211"
+         */
+        private final String endpoint;
+        /**
+         * the working directory of the service. Can be "/path/to/dir"
+         * <p>
+         * default is "/"
+         */
+        private final String root;
+        /**
+         * Memcached username, optional.
+         */
+        private final String username;
+        /**
+         * Memcached password, optional.
+         */
+        private final String password;
+        /**
+         * The default ttl for put operations.
+         */
+        private final Duration defaultTtl;
+
+        @Override
+        public String scheme() {
+            return "memcached";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (username != null) {
+                map.put("username", username);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            if (defaultTtl != null) {
+                map.put("default_ttl", defaultTtl.toString());
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Memory implements ServiceConfig {
+        /**
+         * root of the backend.
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "memory";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class MiniMoka implements ServiceConfig {
+        /**
+         * Sets the max capacity of the cache.
+         * <p>
+         * Refer to 
[`mini-moka::sync::CacheBuilder::max_capacity`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.max_capacity)
+         */
+        private final Long maxCapacity;
+        /**
+         * Sets the time to live of the cache.
+         * <p>
+         * Refer to 
[`mini-moka::sync::CacheBuilder::time_to_live`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.time_to_live)
+         */
+        private final Duration timeToLive;
+        /**
+         * Sets the time to idle of the cache.
+         * <p>
+         * Refer to 
[`mini-moka::sync::CacheBuilder::time_to_idle`](https://docs.rs/mini-moka/latest/mini_moka/sync/struct.CacheBuilder.html#method.time_to_idle)
+         */
+        private final Duration timeToIdle;
+        /**
+         * root path of this backend
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "mini_moka";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (maxCapacity != null) {
+                map.put("max_capacity", String.valueOf(maxCapacity));
+            }
+            if (timeToLive != null) {
+                map.put("time_to_live", timeToLive.toString());
+            }
+            if (timeToIdle != null) {
+                map.put("time_to_idle", timeToIdle.toString());
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Moka implements ServiceConfig {
+        /**
+         * Name for this cache instance.
+         */
+        private final String name;
+        /**
+         * Sets the max capacity of the cache.
+         * <p>
+         * Refer to 
[`moka::sync::CacheBuilder::max_capacity`](https://docs.rs/moka/latest/moka/sync/struct.CacheBuilder.html#method.max_capacity)
+         */
+        private final Long maxCapacity;
+        /**
+         * Sets the time to live of the cache.
+         * <p>
+         * Refer to 
[`moka::sync::CacheBuilder::time_to_live`](https://docs.rs/moka/latest/moka/sync/struct.CacheBuilder.html#method.time_to_live)
+         */
+        private final Duration timeToLive;
+        /**
+         * Sets the time to idle of the cache.
+         * <p>
+         * Refer to 
[`moka::sync::CacheBuilder::time_to_idle`](https://docs.rs/moka/latest/moka/sync/struct.CacheBuilder.html#method.time_to_idle)
+         */
+        private final Duration timeToIdle;
+        /**
+         * Sets the segments number of the cache.
+         * <p>
+         * Refer to 
[`moka::sync::CacheBuilder::segments`](https://docs.rs/moka/latest/moka/sync/struct.CacheBuilder.html#method.segments)
+         */
+        private final Long numSegments;
+        /**
+         * root path of this backend
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "moka";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (name != null) {
+                map.put("name", name);
+            }
+            if (maxCapacity != null) {
+                map.put("max_capacity", String.valueOf(maxCapacity));
+            }
+            if (timeToLive != null) {
+                map.put("time_to_live", timeToLive.toString());
+            }
+            if (timeToIdle != null) {
+                map.put("time_to_idle", timeToIdle.toString());
+            }
+            if (numSegments != null) {
+                map.put("num_segments", String.valueOf(numSegments));
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Mongodb implements ServiceConfig {
+        /**
+         * connection string of this backend
+         */
+        private final String connectionString;
+        /**
+         * database of this backend
+         */
+        private final String database;
+        /**
+         * collection of this backend
+         */
+        private final String collection;
+        /**
+         * root of this backend
+         */
+        private final String root;
+        /**
+         * key field of this backend
+         */
+        private final String keyField;
+        /**
+         * value field of this backend
+         */
+        private final String valueField;
+
+        @Override
+        public String scheme() {
+            return "mongodb";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (connectionString != null) {
+                map.put("connection_string", connectionString);
+            }
+            if (database != null) {
+                map.put("database", database);
+            }
+            if (collection != null) {
+                map.put("collection", collection);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (keyField != null) {
+                map.put("key_field", keyField);
+            }
+            if (valueField != null) {
+                map.put("value_field", valueField);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Monoiofs implements ServiceConfig {
+        /**
+         * The Root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         * <p>
+         * Builder::build will return error if not set.
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "monoiofs";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Mysql implements ServiceConfig {
+        /**
+         * This connection string is used to connect to the mysql service. 
There are url based formats:
+         * <p>
+         * ## Url
+         * <p>
+         * This format resembles the url format of the mysql client. The 
format is: 
`[scheme://][user[:[password]]@]host[:port][/schema][?attribute1=value1&attribute2=value2...`
+         * <p>
+         * - `mysql://user@localhost`
+         * - `mysql://user:password@localhost`
+         * - `mysql://user:password@localhost:3306`
+         * - `mysql://user:password@localhost:3306/db`
+         * <p>
+         * For more information, please refer to 
<https://docs.rs/sqlx/latest/sqlx/mysql/struct.MySqlConnectOptions.html>.
+         */
+        private final String connectionString;
+        /**
+         * The table name for mysql.
+         */
+        private final String table;
+        /**
+         * The key field name for mysql.
+         */
+        private final String keyField;
+        /**
+         * The value field name for mysql.
+         */
+        private final String valueField;
+        /**
+         * The root for mysql.
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "mysql";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (connectionString != null) {
+                map.put("connection_string", connectionString);
+            }
+            if (table != null) {
+                map.put("table", table);
+            }
+            if (keyField != null) {
+                map.put("key_field", keyField);
+            }
+            if (valueField != null) {
+                map.put("value_field", valueField);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class NebulaGraph implements ServiceConfig {
+        /**
+         * The host addr of nebulagraph's graphd server
+         */
+        private final String host;
+        /**
+         * The host port of nebulagraph's graphd server
+         */
+        private final Integer port;
+        /**
+         * The username of nebulagraph's graphd server
+         */
+        private final String username;
+        /**
+         * The password of nebulagraph's graphd server
+         */
+        private final String password;
+        /**
+         * The space name of nebulagraph's graphd server
+         */
+        private final String space;
+        /**
+         * The tag name of nebulagraph's graphd server
+         */
+        private final String tag;
+        /**
+         * The key field name of the NebulaGraph service to read/write.
+         */
+        private final String keyField;
+        /**
+         * The value field name of the NebulaGraph service to read/write.
+         */
+        private final String valueField;
+        /**
+         * The root for NebulaGraph
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "nebula_graph";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (host != null) {
+                map.put("host", host);
+            }
+            if (port != null) {
+                map.put("port", String.valueOf(port));
+            }
+            if (username != null) {
+                map.put("username", username);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            if (space != null) {
+                map.put("space", space);
+            }
+            if (tag != null) {
+                map.put("tag", tag);
+            }
+            if (keyField != null) {
+                map.put("key_field", keyField);
+            }
+            if (valueField != null) {
+                map.put("value_field", valueField);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Obs implements ServiceConfig {
+        /**
+         * Root for obs.
+         */
+        private final String root;
+        /**
+         * Endpoint for obs.
+         */
+        private final String endpoint;
+        /**
+         * Access key id for obs.
+         */
+        private final String accessKeyId;
+        /**
+         * Secret access key for obs.
+         */
+        private final String secretAccessKey;
+        /**
+         * Bucket for obs.
+         */
+        private final String bucket;
+
+        @Override
+        public String scheme() {
+            return "obs";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (accessKeyId != null) {
+                map.put("access_key_id", accessKeyId);
+            }
+            if (secretAccessKey != null) {
+                map.put("secret_access_key", secretAccessKey);
+            }
+            if (bucket != null) {
+                map.put("bucket", bucket);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Onedrive implements ServiceConfig {
+        /**
+         * bearer access token for OneDrive
+         */
+        private final String accessToken;
+        /**
+         * root path of OneDrive folder.
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "onedrive";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (accessToken != null) {
+                map.put("access_token", accessToken);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Oss implements ServiceConfig {
+        /**
+         * Bucket for oss.
+         */
+        private final @NonNull String bucket;
+        /**
+         * Root for oss.
+         */
+        private final String root;
+        /**
+         * Endpoint for oss.
+         */
+        private final String endpoint;
+        /**
+         * Presign endpoint for oss.
+         */
+        private final String presignEndpoint;
+        /**
+         * Server side encryption for oss.
+         */
+        private final String serverSideEncryption;
+        /**
+         * Server side encryption key id for oss.
+         */
+        private final String serverSideEncryptionKeyId;
+        /**
+         * Allow anonymous for oss.
+         */
+        private final Boolean allowAnonymous;
+        /**
+         * Access key id for oss.
+         */
+        private final String accessKeyId;
+        /**
+         * Access key secret for oss.
+         */
+        private final String accessKeySecret;
+        /**
+         * The size of max batch operations.
+         *
+         * @deprecated Please use `delete_max_size` instead of 
`batch_max_operations`
+         */
+        private final Long batchMaxOperations;
+        /**
+         * The size of max delete operations.
+         */
+        private final Long deleteMaxSize;
+        /**
+         * If `role_arn` is set, we will use already known config as source
+         * credential to assume role with `role_arn`.
+         */
+        private final String roleArn;
+        /**
+         * role_session_name for this backend.
+         */
+        private final String roleSessionName;
+        /**
+         * `oidc_provider_arn` will be loaded from
+         * <p>
+         * - this field if it's `is_some`
+         * - env value: [`ALIBABA_CLOUD_OIDC_PROVIDER_ARN`]
+         */
+        private final String oidcProviderArn;
+        /**
+         * `oidc_token_file` will be loaded from
+         * <p>
+         * - this field if it's `is_some`
+         * - env value: [`ALIBABA_CLOUD_OIDC_TOKEN_FILE`]
+         */
+        private final String oidcTokenFile;
+        /**
+         * `sts_endpoint` will be loaded from
+         * <p>
+         * - this field if it's `is_some`
+         * - env value: [`ALIBABA_CLOUD_STS_ENDPOINT`]
+         */
+        private final String stsEndpoint;
+
+        @Override
+        public String scheme() {
+            return "oss";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("bucket", bucket);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (presignEndpoint != null) {
+                map.put("presign_endpoint", presignEndpoint);
+            }
+            if (serverSideEncryption != null) {
+                map.put("server_side_encryption", serverSideEncryption);
+            }
+            if (serverSideEncryptionKeyId != null) {
+                map.put("server_side_encryption_key_id", 
serverSideEncryptionKeyId);
+            }
+            if (allowAnonymous != null) {
+                map.put("allow_anonymous", String.valueOf(allowAnonymous));
+            }
+            if (accessKeyId != null) {
+                map.put("access_key_id", accessKeyId);
+            }
+            if (accessKeySecret != null) {
+                map.put("access_key_secret", accessKeySecret);
+            }
+            if (batchMaxOperations != null) {
+                map.put("batch_max_operations", 
String.valueOf(batchMaxOperations));
+            }
+            if (deleteMaxSize != null) {
+                map.put("delete_max_size", String.valueOf(deleteMaxSize));
+            }
+            if (roleArn != null) {
+                map.put("role_arn", roleArn);
+            }
+            if (roleSessionName != null) {
+                map.put("role_session_name", roleSessionName);
+            }
+            if (oidcProviderArn != null) {
+                map.put("oidc_provider_arn", oidcProviderArn);
+            }
+            if (oidcTokenFile != null) {
+                map.put("oidc_token_file", oidcTokenFile);
+            }
+            if (stsEndpoint != null) {
+                map.put("sts_endpoint", stsEndpoint);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Pcloud implements ServiceConfig {
+        /**
+         * pCloud  endpoint address.
+         */
+        private final @NonNull String endpoint;
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         */
+        private final String root;
+        /**
+         * pCloud username.
+         */
+        private final String username;
+        /**
+         * pCloud password.
+         */
+        private final String password;
+
+        @Override
+        public String scheme() {
+            return "pcloud";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("endpoint", endpoint);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (username != null) {
+                map.put("username", username);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Persy implements ServiceConfig {
+        /**
+         * That path to the persy data file. The directory in the path must 
already exist.
+         */
+        private final String datafile;
+        /**
+         * That name of the persy segment.
+         */
+        private final String segment;
+        /**
+         * That name of the persy index.
+         */
+        private final String index;
+
+        @Override
+        public String scheme() {
+            return "persy";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (datafile != null) {
+                map.put("datafile", datafile);
+            }
+            if (segment != null) {
+                map.put("segment", segment);
+            }
+            if (index != null) {
+                map.put("index", index);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Postgresql implements ServiceConfig {
+        /**
+         * Root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         * <p>
+         * Default to `/` if not set.
+         */
+        private final String root;
+        /**
+         * The URL should be with a scheme of either `postgres://` or 
`postgresql://`.
+         * <p>
+         * - `postgresql://user@localhost`
+         * - 
`postgresql://user:password@%2Fvar%2Flib%2Fpostgresql/mydb?connect_timeout=10`
+         * - 
`postgresql://user@host1:1234,host2,host3:5678?target_session_attrs=read-write`
+         * - `postgresql:///mydb?user=user&host=/var/lib/postgresql`
+         * <p>
+         * For more information, please visit 
<https://docs.rs/sqlx/latest/sqlx/postgres/struct.PgConnectOptions.html>.
+         */
+        private final String connectionString;
+        /**
+         * the table of postgresql
+         */
+        private final String table;
+        /**
+         * the key field of postgresql
+         */
+        private final String keyField;
+        /**
+         * the value field of postgresql
+         */
+        private final String valueField;
+
+        @Override
+        public String scheme() {
+            return "postgresql";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (connectionString != null) {
+                map.put("connection_string", connectionString);
+            }
+            if (table != null) {
+                map.put("table", table);
+            }
+            if (keyField != null) {
+                map.put("key_field", keyField);
+            }
+            if (valueField != null) {
+                map.put("value_field", valueField);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Redb implements ServiceConfig {
+        /**
+         * path to the redb data directory.
+         */
+        private final String datadir;
+        /**
+         * The root for redb.
+         */
+        private final String root;
+        /**
+         * The table name for redb.
+         */
+        private final String table;
+
+        @Override
+        public String scheme() {
+            return "redb";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (datadir != null) {
+                map.put("datadir", datadir);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (table != null) {
+                map.put("table", table);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Redis implements ServiceConfig {
+        /**
+         * the number of DBs redis can take is unlimited
+         * <p>
+         * default is db 0
+         */
+        private final long db;
+        /**
+         * network address of the Redis service. Can be 
"tcp://127.0.0.1:6379", e.g.
+         * <p>
+         * default is "tcp://127.0.0.1:6379"
+         */
+        private final String endpoint;
+        /**
+         * network address of the Redis cluster service. Can be 
"tcp://127.0.0.1:6379,tcp://127.0.0.1:6380,tcp://127.0.0.1:6381", e.g.
+         * <p>
+         * default is None
+         */
+        private final String clusterEndpoints;
+        /**
+         * the username to connect redis service.
+         * <p>
+         * default is None
+         */
+        private final String username;
+        /**
+         * the password for authentication
+         * <p>
+         * default is None
+         */
+        private final String password;
+        /**
+         * the working directory of the Redis service. Can be "/path/to/dir"
+         * <p>
+         * default is "/"
+         */
+        private final String root;
+        /**
+         * The default ttl for put operations.
+         */
+        private final Duration defaultTtl;
+
+        @Override
+        public String scheme() {
+            return "redis";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("db", String.valueOf(db));
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (clusterEndpoints != null) {
+                map.put("cluster_endpoints", clusterEndpoints);
+            }
+            if (username != null) {
+                map.put("username", username);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (defaultTtl != null) {
+                map.put("default_ttl", defaultTtl.toString());
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class S3 implements ServiceConfig {
+        /**
+         * bucket name of this backend.
+         * <p>
+         * required.
+         */
+        private final @NonNull String bucket;
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         * <p>
+         * default to `/` if not set.
+         */
+        private final String root;
+        /**
+         * is bucket versioning enabled for this bucket
+         */
+        private final Boolean enableVersioning;
+        /**
+         * endpoint of this backend.
+         * <p>
+         * Endpoint must be full uri, e.g.
+         * <p>
+         * - AWS S3: `https://s3.amazonaws.com` or 
`https://s3.{region}.amazonaws.com`
+         * - Cloudflare R2: `https://<ACCOUNT_ID>.r2.cloudflarestorage.com`
+         * - Aliyun OSS: `https://{region}.aliyuncs.com`
+         * - Tencent COS: `https://cos.{region}.myqcloud.com`
+         * - Minio: `http://127.0.0.1:9000`
+         * <p>
+         * If user inputs endpoint without scheme like "s3.amazonaws.com", we
+         * will prepend "https://"; before it.
+         * <p>
+         * - If endpoint is set, we will take user's input first.
+         * - If not, we will try to load it from environment.
+         * - If still not set, default to `https://s3.amazonaws.com`.
+         */
+        private final String endpoint;
+        /**
+         * Region represent the signing region of this endpoint. This is 
required
+         * if you are using the default AWS S3 endpoint.
+         * <p>
+         * If using a custom endpoint,
+         * - If region is set, we will take user's input first.
+         * - If not, we will try to load it from environment.
+         */
+        private final String region;
+        /**
+         * access_key_id of this backend.
+         * <p>
+         * - If access_key_id is set, we will take user's input first.
+         * - If not, we will try to load it from environment.
+         */
+        private final String accessKeyId;
+        /**
+         * secret_access_key of this backend.
+         * <p>
+         * - If secret_access_key is set, we will take user's input first.
+         * - If not, we will try to load it from environment.
+         */
+        private final String secretAccessKey;
+        /**
+         * session_token (aka, security token) of this backend.
+         * <p>
+         * This token will expire after sometime, it's recommended to set 
session_token
+         * by hand.
+         */
+        private final String sessionToken;
+        /**
+         * role_arn for this backend.
+         * <p>
+         * If `role_arn` is set, we will use already known config as source
+         * credential to assume role with `role_arn`.
+         */
+        private final String roleArn;
+        /**
+         * external_id for this backend.
+         */
+        private final String externalId;
+        /**
+         * role_session_name for this backend.
+         */
+        private final String roleSessionName;
+        /**
+         * Disable config load so that opendal will not load config from
+         * environment.
+         * <p>
+         * For examples:
+         * <p>
+         * - envs like `AWS_ACCESS_KEY_ID`
+         * - files like `~/.aws/config`
+         */
+        private final Boolean disableConfigLoad;
+        /**
+         * Disable load credential from ec2 metadata.
+         * <p>
+         * This option is used to disable the default behavior of opendal
+         * to load credential from ec2 metadata, a.k.a, IMDSv2
+         */
+        private final Boolean disableEc2Metadata;
+        /**
+         * Allow anonymous will allow opendal to send request without signing
+         * when credential is not loaded.
+         */
+        private final Boolean allowAnonymous;
+        /**
+         * server_side_encryption for this backend.
+         * <p>
+         * Available values: `AES256`, `aws:kms`.
+         */
+        private final String serverSideEncryption;
+        /**
+         * server_side_encryption_aws_kms_key_id for this backend
+         * <p>
+         * - If `server_side_encryption` set to `aws:kms`, and 
`server_side_encryption_aws_kms_key_id`
+         * is not set, S3 will use aws managed kms key to encrypt data.
+         * - If `server_side_encryption` set to `aws:kms`, and 
`server_side_encryption_aws_kms_key_id`
+         * is a valid kms key id, S3 will use the provided kms key to encrypt 
data.
+         * - If the `server_side_encryption_aws_kms_key_id` is invalid or not 
found, an error will be
+         * returned.
+         * - If `server_side_encryption` is not `aws:kms`, setting 
`server_side_encryption_aws_kms_key_id`
+         * is a noop.
+         */
+        private final String serverSideEncryptionAwsKmsKeyId;
+        /**
+         * server_side_encryption_customer_algorithm for this backend.
+         * <p>
+         * Available values: `AES256`.
+         */
+        private final String serverSideEncryptionCustomerAlgorithm;
+        /**
+         * server_side_encryption_customer_key for this backend.
+         * <p>
+         * # Value
+         * <p>
+         * base64 encoded key that matches algorithm specified in
+         * `server_side_encryption_customer_algorithm`.
+         */
+        private final String serverSideEncryptionCustomerKey;
+        /**
+         * Set server_side_encryption_customer_key_md5 for this backend.
+         * <p>
+         * # Value
+         * <p>
+         * MD5 digest of key specified in 
`server_side_encryption_customer_key`.
+         */
+        private final String serverSideEncryptionCustomerKeyMd5;
+        /**
+         * default storage_class for this backend.
+         * <p>
+         * Available values:
+         * - `DEEP_ARCHIVE`
+         * - `GLACIER`
+         * - `GLACIER_IR`
+         * - `INTELLIGENT_TIERING`
+         * - `ONEZONE_IA`
+         * - `OUTPOSTS`
+         * - `REDUCED_REDUNDANCY`
+         * - `STANDARD`
+         * - `STANDARD_IA`
+         * <p>
+         * S3 compatible services don't support all of them
+         */
+        private final String defaultStorageClass;
+        /**
+         * Enable virtual host style so that opendal will send API requests
+         * in virtual host style instead of path style.
+         * <p>
+         * - By default, opendal will send API to 
`https://s3.us-east-1.amazonaws.com/bucket_name`
+         * - Enabled, opendal will send API to 
`https://bucket_name.s3.us-east-1.amazonaws.com`
+         */
+        private final Boolean enableVirtualHostStyle;
+        /**
+         * Set maximum batch operations of this backend.
+         * <p>
+         * Some compatible services have a limit on the number of operations 
in a batch request.
+         * For example, R2 could return `Internal Error` while batch delete 
1000 files.
+         * <p>
+         * Please tune this value based on services' document.
+         *
+         * @deprecated Please use `delete_max_size` instead of 
`batch_max_operations`
+         */
+        private final Long batchMaxOperations;
+        /**
+         * Set the maximum delete size of this backend.
+         * <p>
+         * Some compatible services have a limit on the number of operations 
in a batch request.
+         * For example, R2 could return `Internal Error` while batch delete 
1000 files.
+         * <p>
+         * Please tune this value based on services' document.
+         */
+        private final Long deleteMaxSize;
+        /**
+         * Disable stat with override so that opendal will not send stat 
request with override queries.
+         * <p>
+         * For example, R2 doesn't support stat with `response_content_type` 
query.
+         */
+        private final Boolean disableStatWithOverride;
+        /**
+         * Checksum Algorithm to use when sending checksums in HTTP headers.
+         * This is necessary when writing to AWS S3 Buckets with Object Lock 
enabled for example.
+         * <p>
+         * Available options:
+         * - "crc32c"
+         */
+        private final String checksumAlgorithm;
+        /**
+         * Disable write with if match so that opendal will not send write 
request with if match headers.
+         * <p>
+         * For example, Ceph RADOS S3 doesn't support write with if match.
+         */
+        private final Boolean disableWriteWithIfMatch;
+
+        @Override
+        public String scheme() {
+            return "s3";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("bucket", bucket);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (enableVersioning != null) {
+                map.put("enable_versioning", String.valueOf(enableVersioning));
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (region != null) {
+                map.put("region", region);
+            }
+            if (accessKeyId != null) {
+                map.put("access_key_id", accessKeyId);
+            }
+            if (secretAccessKey != null) {
+                map.put("secret_access_key", secretAccessKey);
+            }
+            if (sessionToken != null) {
+                map.put("session_token", sessionToken);
+            }
+            if (roleArn != null) {
+                map.put("role_arn", roleArn);
+            }
+            if (externalId != null) {
+                map.put("external_id", externalId);
+            }
+            if (roleSessionName != null) {
+                map.put("role_session_name", roleSessionName);
+            }
+            if (disableConfigLoad != null) {
+                map.put("disable_config_load", 
String.valueOf(disableConfigLoad));
+            }
+            if (disableEc2Metadata != null) {
+                map.put("disable_ec2_metadata", 
String.valueOf(disableEc2Metadata));
+            }
+            if (allowAnonymous != null) {
+                map.put("allow_anonymous", String.valueOf(allowAnonymous));
+            }
+            if (serverSideEncryption != null) {
+                map.put("server_side_encryption", serverSideEncryption);
+            }
+            if (serverSideEncryptionAwsKmsKeyId != null) {
+                map.put("server_side_encryption_aws_kms_key_id", 
serverSideEncryptionAwsKmsKeyId);
+            }
+            if (serverSideEncryptionCustomerAlgorithm != null) {
+                map.put("server_side_encryption_customer_algorithm", 
serverSideEncryptionCustomerAlgorithm);
+            }
+            if (serverSideEncryptionCustomerKey != null) {
+                map.put("server_side_encryption_customer_key", 
serverSideEncryptionCustomerKey);
+            }
+            if (serverSideEncryptionCustomerKeyMd5 != null) {
+                map.put("server_side_encryption_customer_key_md5", 
serverSideEncryptionCustomerKeyMd5);
+            }
+            if (defaultStorageClass != null) {
+                map.put("default_storage_class", defaultStorageClass);
+            }
+            if (enableVirtualHostStyle != null) {
+                map.put("enable_virtual_host_style", 
String.valueOf(enableVirtualHostStyle));
+            }
+            if (batchMaxOperations != null) {
+                map.put("batch_max_operations", 
String.valueOf(batchMaxOperations));
+            }
+            if (deleteMaxSize != null) {
+                map.put("delete_max_size", String.valueOf(deleteMaxSize));
+            }
+            if (disableStatWithOverride != null) {
+                map.put("disable_stat_with_override", 
String.valueOf(disableStatWithOverride));
+            }
+            if (checksumAlgorithm != null) {
+                map.put("checksum_algorithm", checksumAlgorithm);
+            }
+            if (disableWriteWithIfMatch != null) {
+                map.put("disable_write_with_if_match", 
String.valueOf(disableWriteWithIfMatch));
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Seafile implements ServiceConfig {
+        /**
+         * repo_name of this backend.
+         * <p>
+         * required.
+         */
+        private final @NonNull String repoName;
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         */
+        private final String root;
+        /**
+         * endpoint address of this backend.
+         */
+        private final String endpoint;
+        /**
+         * username of this backend.
+         */
+        private final String username;
+        /**
+         * password of this backend.
+         */
+        private final String password;
+
+        @Override
+        public String scheme() {
+            return "seafile";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("repo_name", repoName);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (username != null) {
+                map.put("username", username);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Sftp implements ServiceConfig {
+        /**
+         * endpoint of this backend
+         */
+        private final String endpoint;
+        /**
+         * root of this backend
+         */
+        private final String root;
+        /**
+         * user of this backend
+         */
+        private final String user;
+        /**
+         * key of this backend
+         */
+        private final String key;
+        /**
+         * known_hosts_strategy of this backend
+         */
+        private final String knownHostsStrategy;
+        /**
+         * enable_copy of this backend
+         */
+        private final Boolean enableCopy;
+
+        @Override
+        public String scheme() {
+            return "sftp";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (user != null) {
+                map.put("user", user);
+            }
+            if (key != null) {
+                map.put("key", key);
+            }
+            if (knownHostsStrategy != null) {
+                map.put("known_hosts_strategy", knownHostsStrategy);
+            }
+            if (enableCopy != null) {
+                map.put("enable_copy", String.valueOf(enableCopy));
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Sled implements ServiceConfig {
+        /**
+         * That path to the sled data directory.
+         */
+        private final String datadir;
+        /**
+         * The root for sled.
+         */
+        private final String root;
+        /**
+         * The tree for sled.
+         */
+        private final String tree;
+
+        @Override
+        public String scheme() {
+            return "sled";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (datadir != null) {
+                map.put("datadir", datadir);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (tree != null) {
+                map.put("tree", tree);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Sqlite implements ServiceConfig {
+        /**
+         * Set the connection_string of the sqlite service.
+         * <p>
+         * This connection string is used to connect to the sqlite service. 
There are url based formats:
+         * <p>
+         * ## Url
+         * <p>
+         * This format resembles the url format of the sqlite client:
+         * <p>
+         * - `sqlite::memory:`
+         * - `sqlite:data.db`
+         * - `sqlite://data.db`
+         * <p>
+         * For more information, please visit 
<https://docs.rs/sqlx/latest/sqlx/sqlite/struct.SqliteConnectOptions.html>.
+         */
+        private final String connectionString;
+        /**
+         * Set the table name of the sqlite service to read/write.
+         */
+        private final String table;
+        /**
+         * Set the key field name of the sqlite service to read/write.
+         * <p>
+         * Default to `key` if not specified.
+         */
+        private final String keyField;
+        /**
+         * Set the value field name of the sqlite service to read/write.
+         * <p>
+         * Default to `value` if not specified.
+         */
+        private final String valueField;
+        /**
+         * set the working directory, all operations will be performed under 
it.
+         * <p>
+         * default: "/"
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "sqlite";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (connectionString != null) {
+                map.put("connection_string", connectionString);
+            }
+            if (table != null) {
+                map.put("table", table);
+            }
+            if (keyField != null) {
+                map.put("key_field", keyField);
+            }
+            if (valueField != null) {
+                map.put("value_field", valueField);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Supabase implements ServiceConfig {
+        /**
+         * The bucket for supabase service.
+         */
+        private final @NonNull String bucket;
+        /**
+         * The root for supabase service.
+         */
+        private final String root;
+        /**
+         * The endpoint for supabase service.
+         */
+        private final String endpoint;
+        /**
+         * The key for supabase service.
+         */
+        private final String key;
+
+        @Override
+        public String scheme() {
+            return "supabase";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("bucket", bucket);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (key != null) {
+                map.put("key", key);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Surrealdb implements ServiceConfig {
+        /**
+         * The connection string for surrealdb.
+         */
+        private final String connectionString;
+        /**
+         * The username for surrealdb.
+         */
+        private final String username;
+        /**
+         * The password for surrealdb.
+         */
+        private final String password;
+        /**
+         * The namespace for surrealdb.
+         */
+        private final String namespace;
+        /**
+         * The database for surrealdb.
+         */
+        private final String database;
+        /**
+         * The table for surrealdb.
+         */
+        private final String table;
+        /**
+         * The key field for surrealdb.
+         */
+        private final String keyField;
+        /**
+         * The value field for surrealdb.
+         */
+        private final String valueField;
+        /**
+         * The root for surrealdb.
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "surrealdb";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (connectionString != null) {
+                map.put("connection_string", connectionString);
+            }
+            if (username != null) {
+                map.put("username", username);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            if (namespace != null) {
+                map.put("namespace", namespace);
+            }
+            if (database != null) {
+                map.put("database", database);
+            }
+            if (table != null) {
+                map.put("table", table);
+            }
+            if (keyField != null) {
+                map.put("key_field", keyField);
+            }
+            if (valueField != null) {
+                map.put("value_field", valueField);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Swift implements ServiceConfig {
+        /**
+         * The endpoint for Swift.
+         */
+        private final String endpoint;
+        /**
+         * The container for Swift.
+         */
+        private final String container;
+        /**
+         * The root for Swift.
+         */
+        private final String root;
+        /**
+         * The token for Swift.
+         */
+        private final String token;
+
+        @Override
+        public String scheme() {
+            return "swift";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (container != null) {
+                map.put("container", container);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (token != null) {
+                map.put("token", token);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Upyun implements ServiceConfig {
+        /**
+         * bucket address of this backend.
+         */
+        private final @NonNull String bucket;
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         */
+        private final String root;
+        /**
+         * username of this backend.
+         */
+        private final String operator;
+        /**
+         * password of this backend.
+         */
+        private final String password;
+
+        @Override
+        public String scheme() {
+            return "upyun";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("bucket", bucket);
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (operator != null) {
+                map.put("operator", operator);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class VercelArtifacts implements ServiceConfig {
+        /**
+         * The access token for Vercel.
+         */
+        private final String accessToken;
+
+        @Override
+        public String scheme() {
+            return "vercel_artifacts";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (accessToken != null) {
+                map.put("access_token", accessToken);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class VercelBlob implements ServiceConfig {
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         */
+        private final String root;
+        /**
+         * vercel blob token.
+         */
+        private final String token;
+
+        @Override
+        public String scheme() {
+            return "vercel_blob";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (token != null) {
+                map.put("token", token);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Webdav implements ServiceConfig {
+        /**
+         * endpoint of this backend
+         */
+        private final String endpoint;
+        /**
+         * username of this backend
+         */
+        private final String username;
+        /**
+         * password of this backend
+         */
+        private final String password;
+        /**
+         * token of this backend
+         */
+        private final String token;
+        /**
+         * root of this backend
+         */
+        private final String root;
+        /**
+         * WebDAV Service doesn't support copy.
+         */
+        private final Boolean disableCopy;
+
+        @Override
+        public String scheme() {
+            return "webdav";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (username != null) {
+                map.put("username", username);
+            }
+            if (password != null) {
+                map.put("password", password);
+            }
+            if (token != null) {
+                map.put("token", token);
+            }
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (disableCopy != null) {
+                map.put("disable_copy", String.valueOf(disableCopy));
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class Webhdfs implements ServiceConfig {
+        /**
+         * Root for webhdfs.
+         */
+        private final String root;
+        /**
+         * Endpoint for webhdfs.
+         */
+        private final String endpoint;
+        /**
+         * Delegation token for webhdfs.
+         */
+        private final String delegation;
+        /**
+         * Disable batch listing
+         */
+        private final Boolean disableListBatch;
+        /**
+         * atomic_write_dir of this backend
+         */
+        private final String atomicWriteDir;
+
+        @Override
+        public String scheme() {
+            return "webhdfs";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            if (root != null) {
+                map.put("root", root);
+            }
+            if (endpoint != null) {
+                map.put("endpoint", endpoint);
+            }
+            if (delegation != null) {
+                map.put("delegation", delegation);
+            }
+            if (disableListBatch != null) {
+                map.put("disable_list_batch", 
String.valueOf(disableListBatch));
+            }
+            if (atomicWriteDir != null) {
+                map.put("atomic_write_dir", atomicWriteDir);
+            }
+            return map;
+        }
+    }
+
+    @Builder
+    @Data
+    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    class YandexDisk implements ServiceConfig {
+        /**
+         * yandex disk oauth access_token.
+         */
+        private final @NonNull String accessToken;
+        /**
+         * root of this backend.
+         * <p>
+         * All operations will happen under this root.
+         */
+        private final String root;
+
+        @Override
+        public String scheme() {
+            return "yandex_disk";
+        }
+
+        @Override
+        public HashMap<String, String> configMap() {
+            final HashMap<String, String> map = new HashMap<>();
+            map.put("access_token", accessToken);
+            if (root != null) {
+                map.put("root", root);
+            }
+            return map;
+        }
+    }
+}
diff --git a/dev/src/generate/java.j2 b/dev/src/generate/java.j2
index 52d9b4b85..976323db3 100644
--- a/dev/src/generate/java.j2
+++ b/dev/src/generate/java.j2
@@ -26,6 +26,7 @@ import java.util.HashMap;
 import lombok.AccessLevel;
 import lombok.Builder;
 import lombok.Data;
+import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 
 /**
@@ -44,12 +45,13 @@ public interface ServiceConfig {
     @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
     class {{srv | case_java_class_name}} implements ServiceConfig {
         {%- for field in srvs[srv].config %}
-        {%- if field.deprecated %}
         /**
+         * {{field.comments}}
+        {%- if field.deprecated %}
          * @deprecated {{field.deprecated["note"]}}
-         */
         {%- endif %}
-        public final {{make_java_type(field.value)}} {{field.name | 
case_java_field_name}};
+         */
+        {{make_field(field)}}
         {%- endfor %}
 
         @Override
@@ -62,7 +64,7 @@ public interface ServiceConfig {
             final HashMap<String, String> map = new HashMap<>();
             {% for field in srvs[srv].config -%}
             {{make_populate_map(field)}}
-            {%- endfor %}
+            {% endfor -%}
             return map;
         }
     }
diff --git a/dev/src/generate/java.rs b/dev/src/generate/java.rs
index 19b0d0d12..2abd51760 100644
--- a/dev/src/generate/java.rs
+++ b/dev/src/generate/java.rs
@@ -34,10 +34,9 @@ pub fn generate(workspace_dir: PathBuf, services: Services) 
-> Result<()> {
     let srvs = sorted_services(services, enabled_service);
     let mut env = Environment::new();
     env.add_template("java", include_str!("java.j2"))?;
-    env.add_function("make_java_type", make_java_type);
+    env.add_function("make_field", make_field);
     env.add_function("make_populate_map", make_populate_map);
     env.add_filter("case_java_class_name", case_java_class_name);
-    env.add_filter("case_java_field_name", case_java_field_name);
     let tmpl = env.get_template("java")?;
 
     let output =
@@ -54,40 +53,70 @@ fn case_java_field_name(s: String) -> String {
     heck::AsLowerCamelCase(s).to_string()
 }
 
-fn make_java_type(ty: ViaDeserialize<ConfigType>) -> Result<String, 
minijinja::Error> {
-    Ok(match ty.0 {
-        ConfigType::Bool => "boolean",
-        ConfigType::Duration => "Duration",
-        ConfigType::I64 | ConfigType::U64 | ConfigType::Usize => "long",
-        ConfigType::U32 | ConfigType::U16 => "int",
-        ConfigType::Vec => "List<String>",
-        ConfigType::String => "String",
-    }
-    .to_string())
+fn make_field(field: ViaDeserialize<Config>) -> Result<String, 
minijinja::Error> {
+    let field_type = if field.optional {
+        match field.value {
+            ConfigType::Bool => "Boolean",
+            ConfigType::String => "String",
+            ConfigType::Duration => "Duration",
+            ConfigType::Usize | ConfigType::U64 | ConfigType::I64 => "Long",
+            ConfigType::U32 | ConfigType::U16 => "Integer",
+            ConfigType::Vec => "List<String>",
+        }
+    } else {
+        match field.value {
+            ConfigType::Bool => "boolean",
+            ConfigType::String => "@NonNull String",
+            ConfigType::Duration => "@NonNull Duration",
+            ConfigType::Usize | ConfigType::U64 | ConfigType::I64 => "long",
+            ConfigType::U32 | ConfigType::U16 => "int",
+            ConfigType::Vec => "@NonNull List<String>",
+        }
+    };
+
+    Ok(format!(
+        "private final {} {};",
+        field_type,
+        case_java_field_name(field.name.clone())
+    ))
 }
 
 fn make_populate_map(field: ViaDeserialize<Config>) -> Result<String, 
minijinja::Error> {
-    let is_primitive_type = match field.value {
-        ConfigType::U64
+    let populate = match field.value {
+        ConfigType::Usize
+        | ConfigType::U64
         | ConfigType::I64
+        | ConfigType::Bool
         | ConfigType::U32
-        | ConfigType::U16
-        | ConfigType::Usize
-        | ConfigType::Bool => true,
-        ConfigType::Duration | ConfigType::Vec | ConfigType::String => false,
+        | ConfigType::U16 => format!(
+            "map.put(\"{}\", String.valueOf({}));",
+            field.name,
+            case_java_field_name(field.name.clone())
+        ),
+        ConfigType::String => format!(
+            "map.put(\"{}\", {});",
+            field.name,
+            case_java_field_name(field.name.clone())
+        ),
+        ConfigType::Duration => format!(
+            "map.put(\"{}\", {}.toString());",
+            field.name,
+            case_java_field_name(field.name.clone())
+        ),
+        ConfigType::Vec => format!(
+            "map.put(\"{}\", String.join(\",\", {}));",
+            field.name,
+            case_java_field_name(field.name.clone())
+        ),
     };
 
-    let field_name = case_java_field_name(field.name.clone());
-    if is_primitive_type {
-        return Ok(format!("map.put(\"{}\", String.valueOf({}));", field.name, 
field_name));
-    }
-
     if field.optional {
-        return Ok(format!(
-            "if ({} != null) map.put(\"{}\", {});",
-            field_name, field.name, field_name
-        ));
+        Ok(format!(
+            "if ({} != null) {{\n    {}\n}}",
+            case_java_field_name(field.name.clone()),
+            populate
+        ))
+    } else {
+        Ok(populate)
     }
-
-    Ok(format!("\nmap.put(\"{}\", {});", field.name, field_name))
 }

Reply via email to