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 166e5fe2db928c7a4ff630fa485d66c33fdabb5c
Author: tison <[email protected]>
AuthorDate: Fri Jan 3 17:29:06 2025 +0800

    feat: generate java configs
    
    Signed-off-by: tison <[email protected]>
---
 dev/src/generate/java.j2   | 46 +++++++++++++++++++++++++++++++++++++
 dev/src/generate/java.rs   | 56 ++++++++++++++++++++++++++++++++++++++++++++++
 dev/src/generate/mod.rs    |  2 ++
 dev/src/generate/parser.rs | 15 +++++++++++++
 dev/src/generate/python.j2 |  2 +-
 dev/src/generate/python.rs | 21 ++++-------------
 6 files changed, 124 insertions(+), 18 deletions(-)

diff --git a/dev/src/generate/java.j2 b/dev/src/generate/java.j2
new file mode 100644
index 000000000..4eda6c496
--- /dev/null
+++ b/dev/src/generate/java.j2
@@ -0,0 +1,46 @@
+/*
+ * 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 lombok.Data;
+
+/**
+  * Service configurations that are mapped from
+  * <a href="https://docs.rs/opendal/*/opendal/services/index.html>OpenDAL's 
services</a>.
+  */
+@SuppressWarnings("unused") // intended to be used by users
+public interface ServiceConfig {
+    {% for srv in srvs %}
+    @Data
+    class {{srv}} {
+        {%- for field in srvs[srv].config %}
+        {%- if field.deprecated %}
+        /**
+         * @deprecated {{field.deprecated["note"]}}
+         */
+        {%- endif %}
+        public final {{make_java_type(field.value)}} {{field.name}};
+        {%- endfor %}
+    }
+    {% endfor %}
+}
diff --git a/dev/src/generate/java.rs b/dev/src/generate/java.rs
new file mode 100644
index 000000000..6de6e153c
--- /dev/null
+++ b/dev/src/generate/java.rs
@@ -0,0 +1,56 @@
+// 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.
+
+use crate::generate::parser::{sorted_services, ConfigType, Services};
+use anyhow::Result;
+use minijinja::value::ViaDeserialize;
+use minijinja::{context, Environment};
+use std::fs;
+use std::path::PathBuf;
+
+fn enabled_service(srv: &str) -> bool {
+    match srv {
+        // not enabled in bindings/java/Cargo.toml
+        "foundationdb" | "ftp" | "hdfs" | "rocksdb" | "tikv" => false,
+        _ => true,
+    }
+}
+
+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);
+    let tmpl = env.get_template("java")?;
+
+    let output =
+        
workspace_dir.join("bindings/java/src/main/java/org/apache/opendal/ServiceConfig.java");
+    fs::write(output, tmpl.render(context! { srvs => srvs })?)?;
+    Ok(())
+}
+
+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())
+}
diff --git a/dev/src/generate/mod.rs b/dev/src/generate/mod.rs
index 780f19a74..2a36ce765 100644
--- a/dev/src/generate/mod.rs
+++ b/dev/src/generate/mod.rs
@@ -15,6 +15,7 @@
 // specific language governing permissions and limitations
 // under the License.
 
+mod java;
 mod parser;
 mod python;
 
@@ -27,6 +28,7 @@ pub fn run(language: &str) -> Result<()> {
     let services = parser::parse(&services_path.to_string_lossy())?;
 
     match language {
+        "java" => java::generate(workspace_dir, services),
         "python" | "py" => python::generate(workspace_dir, services),
         _ => anyhow::bail!("unsupported language: {}", language),
     }
diff --git a/dev/src/generate/parser.rs b/dev/src/generate/parser.rs
index 086d7be5a..ee4bc4d4c 100644
--- a/dev/src/generate/parser.rs
+++ b/dev/src/generate/parser.rs
@@ -29,6 +29,21 @@ use syn::{
 
 pub type Services = HashMap<String, Service>;
 
+pub fn sorted_services(services: Services, test: fn(&str) -> bool) -> Services 
{
+    let mut srvs = Services::new();
+    for (k, srv) in services.into_iter() {
+        if !test(k.as_str()) {
+            continue;
+        }
+
+        let mut sorted = 
srv.config.into_iter().enumerate().collect::<Vec<_>>();
+        sorted.sort_by_key(|(i, v)| (v.optional, *i));
+        let config = sorted.into_iter().map(|(_, v)| v).collect();
+        srvs.insert(k, Service { config });
+    }
+    srvs
+}
+
 /// Service represents a service supported by opendal core, like `s3` and `fs`
 #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
 pub struct Service {
diff --git a/dev/src/generate/python.j2 b/dev/src/generate/python.j2
index 772407d52..49036d278 100644
--- a/dev/src/generate/python.j2
+++ b/dev/src/generate/python.j2
@@ -54,7 +54,7 @@ class _Base:
         {% if field.deprecated %}
         # deprecated: {{field.deprecated["note"]}}
         {%- endif %}
-        {{field.name}}: {{make_pytype(field.value)}}{% if field.optional %} = 
...{% endif %},
+        {{field.name}}: {{make_python_type(field.value)}}{% if field.optional 
%} = ...{% endif %},
     {%- endfor %}
     ) -> None: ...
 {% endfor %}
diff --git a/dev/src/generate/python.rs b/dev/src/generate/python.rs
index 268a6e89d..0e852ed0c 100644
--- a/dev/src/generate/python.rs
+++ b/dev/src/generate/python.rs
@@ -15,14 +15,13 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use crate::generate::parser::{ConfigType, Service, Services};
+use crate::generate::parser::{sorted_services, ConfigType, Services};
 use anyhow::Result;
 use minijinja::value::ViaDeserialize;
 use minijinja::{context, Environment};
 use std::fs;
 use std::path::PathBuf;
 
-/// TODO: add a common utils to parse enabled features from cargo.toml
 fn enabled_service(srv: &str) -> bool {
     match srv {
         // not enabled in bindings/python/Cargo.toml
@@ -32,30 +31,18 @@ fn enabled_service(srv: &str) -> bool {
 }
 
 pub fn generate(workspace_dir: PathBuf, services: Services) -> Result<()> {
-    let mut srvs = Services::new();
-    for (k, srv) in services.into_iter() {
-        if !enabled_service(k.as_str()) {
-            continue;
-        }
-
-        let mut sorted = 
srv.config.into_iter().enumerate().collect::<Vec<_>>();
-        sorted.sort_by_key(|(i, v)| (v.optional, *i));
-        let config = sorted.into_iter().map(|(_, v)| v).collect();
-        srvs.insert(k, Service { config });
-    }
-
+    let srvs = sorted_services(services, enabled_service);
     let mut env = Environment::new();
     env.add_template("python", include_str!("python.j2"))?;
-    env.add_function("make_pytype", make_pytype);
+    env.add_function("make_python_type", make_python_type);
     let tmpl = env.get_template("python")?;
 
     let output = 
workspace_dir.join("bindings/python/python/opendal/__base.pyi");
     fs::write(output, tmpl.render(context! { srvs => srvs })?)?;
-
     Ok(())
 }
 
-fn make_pytype(ty: ViaDeserialize<ConfigType>) -> Result<String, 
minijinja::Error> {
+fn make_python_type(ty: ViaDeserialize<ConfigType>) -> Result<String, 
minijinja::Error> {
     Ok(match ty.0 {
         ConfigType::Bool => "_bool",
         ConfigType::Duration => "_duration",

Reply via email to