You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by ti...@apache.org on 2025/01/03 10:36:50 UTC
(opendal) 01/05: feat: generate java configs
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 <wa...@gmail.com>
AuthorDate: Fri Jan 3 17:29:06 2025 +0800
feat: generate java configs
Signed-off-by: tison <wa...@gmail.com>
---
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",