Java API
正在查找跨语言 FFI 契约? 请参阅
./ffi-abi.md,了解call、call_with_plugin_agent、"ERROR:"前缀、4 MiB 的BUFFER_SIZE以及kcl_lib_jni共享库。 下面的com.kcl.api.API类是上述单一调度器的轻量 JNI 包装器; 每个类型化方法都通过call(args)进行分发。
Java 绑定 通过 GitHub Packages 发布为 Maven 工件,分为两层:
com.kcl.api.API— 实现类型化 RPC 表面的 Java 类。每个方法都会 序列化其Spec.*Argsproto,通过 JNI 调用原生call(args),解析结果 proto, 并将调度器的"ERROR:..."应答作为抛出的Exception暴露给调用方。com.kcl.api.Spec— 由spec/spec.proto自动生成的 protobuf 类。
安装
请参考这里配置 Maven;在 settings.xml 中设置您的 GitHub 账号和 Token。
Maven
在您项目的 pom.xml 中,按如下方式配置我们的仓库:
<repositories>
<repository>
<id>github</id>
<url>https://maven.pkg.github.com/kcl-lang/*</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
通过这种方式,您即可引入上述依赖以使用 SDK。
<dependency>
<groupId>com.kcl</groupId>
<artifactId>kcl-lib</artifactId>
<version>0.13.0</version>
</dependency>
快速开始
import com.kcl.api.API;
import com.kcl.api.Spec.ExecProgramArgs;
import com.kcl.api.Spec.ExecProgramResult;
public class ExecProgramTest {
public static void main(String[] args) throws Exception {
API api = new API();
ExecProgramResult result = api
.execProgram(ExecProgramArgs.newBuilder().addKFilenameList("path/to/kcl.k").build());
System.out.println(result.getYamlResult());
}
}
API 参考
execProgram
使用参数执行 KCL 文件,并返回 JSON/YAML 结果。
示例
schema.k 的内容为
schema AppConfig:
replicas: int
app: AppConfig {
replicas: 2
}
Java 代码
import com.kcl.api.*;
ExecProgramArgs args = ExecProgramArgs.newBuilder().addKFilenameList("schema.k").build();
API apiInstance = new API();
ExecProgramResult result = apiInstance.execProgram(args);
parseFile
将 KCL 单个文件解析为 Module AST JSON 字符串,包含导入依赖与解析错误。
示例
schema.k 的内容为
schema AppConfig:
replicas: int
app: AppConfig {
replicas: 2
}
Java 代码
import com.kcl.api.*;
ParseFileArgs args = ParseFileArgs.newBuilder().setPath("schema.k").build();
API apiInstance = new API();
ParseFileResult result = apiInstance.parseFile(args);
parseProgram
使用入口文件解析 KCL 程序,并返回 AST JSON 字符串。
示例
schema.k 的内容为
schema AppConfig:
replicas: int
app: AppConfig {
replicas: 2
}
Java 代码
import com.kcl.api.*;
import com.kcl.ast.*;
import com.kcl.util.JsonUtil;
API api = new API();
ParseProgramResult result = api.parseProgram(
ParseProgramArgs.newBuilder().addPaths("path/to/kcl.k").build()
);
System.out.println(result.getAstJson());
Program program = JsonUtil.deserializeProgram(result.getAstJson());
loadPackage
loadPackage 为用户提供了解析 KCL 程序以及语义模型信息(包括符号、类型、定义等)的能力。
示例
schema.k 的内容为
schema AppConfig:
replicas: int
app: AppConfig {
replicas: 2
}
Java 代码
import com.kcl.api.*;
API api = new API();
LoadPackageResult result = api.loadPackage(LoadPackageArgs.newBuilder().setResolveAst(true)
.setWithAstIndex(true)
.setParseArgs(ParseProgramArgs.newBuilder().addPaths("schema.k").build()).build());
listVariables
listVariables 为用户提供了解析 KCL 程序并按 specs 获取所有变量的能力。
示例
schema.k 的内容为
schema AppConfig:
replicas: int
app: AppConfig {
replicas: 2
}
Java 代码
import com.kcl.api.*;
API api = new API();
ListVariablesResult result = api.listVariables(
ListVariablesArgs.newBuilder().setResolveAst(true).setParseArgs(
ParseProgramArgs.newBuilder().addPaths("/path/to/kcl.k").build())
.build());
result.getSymbolsMap().values().forEach(s -> System.out.println(s));
listOptions
listOptions 为用户提供了解析 KCL 程序并获取所有 option 信息的能力。
示例
options.k 的内容为
a = option("key1")
b = option("key2", required=True)
c = {
metadata.key = option("metadata-key")
}
Java 代码
import com.kcl.api.*;
ParseProgramArgs args = ParseProgramArgs.newBuilder().addPaths("./src/test_data/option/main.k").build();
API apiInstance = new API();
ListOptionsResult result = apiInstance.listOptions(args);
getSchemaTypeMapping
获取程序中定义的 schema 类型映射。
示例
schema.k 的内容为
schema AppConfig:
replicas: int
app: AppConfig {
replicas: 2
}
Java 代码
import com.kcl.api.*;
ExecProgramArgs execArgs = ExecProgramArgs.newBuilder().addKFilenameList("schema.k").build();
GetSchemaTypeMappingArgs args = GetSchemaTypeMappingArgs.newBuilder().setExecArgs(execArgs).build();
API apiInstance = new API();
GetSchemaTypeMappingResult result = apiInstance.getSchemaTypeMapping(args);
KclType appSchemaType = result.getSchemaTypeMappingMap().get("app");
String replicasType = appSchemaType.getPropertiesOrThrow("replicas").getType();
getSchemaTypeMappingUnderPath
获取程序及其依赖包中定义的 schema 类型映射,以包名作为键。
与 getSchemaTypeMapping 不同,从外部依赖包导入的 schema 会以其自身的包名作为键,
而不是被扁平化到 __main__ 下。
示例
Java 代码
import com.kcl.api.*;
import java.nio.file.Path;
import java.nio.file.Paths;
Path root = Paths.get("test_data/get_schema_ty_under_path").toAbsolutePath();
ExecProgramArgs execArgs = ExecProgramArgs.newBuilder()
.addKFilenameList(root.resolve("aaa").toString())
.addExternalPkgs(ExternalPkg.newBuilder().setPkgName("bbb")
.setPkgPath(root.resolve("bbb").toString()).build())
.build();
GetSchemaTypeMappingArgs args = GetSchemaTypeMappingArgs.newBuilder().setExecArgs(execArgs).build();
API apiInstance = new API();
GetSchemaTypeMappingUnderPathResult result = apiInstance.getSchemaTypeMappingUnderPath(args);
KclType base = result.getSchemaTypeMappingOrThrow("bbb").getSchemaTypeList().stream()
.filter(s -> s.getSchemaName().equals("Base")).findFirst().orElseThrow();
overrideFile
使用参数覆盖 KCL 文件。有关更多覆盖 spec 指南,请参阅 https://www.kcl-lang.io/docs/user_docs/guides/automation。
示例
main.k 的内容为
a = 1
b = {
"a": 1
"b": 2
}
Java 代码
import com.kcl.api.*;
API api = new API();
String spec = "a=2";
OverrideFileResult result = api.overrideFile(OverrideFileArgs.newBuilder()
.setFile("./src/test_data/override_file/main.k").addSpecs(spec).build());
formatCode
格式化代码源码。
示例
Java 代码
import com.kcl.api.*;
String sourceCode = "schema Person:\n" + " name: str\n" + " age: int\n" + " check:\n"
+ " 0 < age < 120\n";
FormatCodeArgs args = FormatCodeArgs.newBuilder().setSource(sourceCode).build();
API apiInstance = new API();
FormatCodeResult result = apiInstance.formatCode(args);
String expectedFormattedCode = "schema Person:\n" + " name: str\n" + " age: int\n\n" + " check:\n"
+ " 0 < age < 120\n\n";
formatPath
格式化 KCL 文件或包含 KCL 文件的目录路径,并返回发生变更的文件路径。
示例
format_path.k 的内容为
schema Person:
name: str
age: int
check:
0 < age < 120
Java 代码
import com.kcl.api.*;
FormatPathArgs args = FormatPathArgs.newBuilder().setPath("format_path.k").build();
API apiInstance = new API();
FormatPathResult result = apiInstance.formatPath(args);
Assert.assertTrue(result.getChangedPathsList().isEmpty());
lintPath
对文件执行 lint,并返回包含错误与警告在内的错误信息。
示例
lint_path.k 的内容为
import math
a = 1
Java 代码
import com.kcl.api.*;
LintPathArgs args = LintPathArgs.newBuilder().addPaths("lint_path.k").build();
API apiInstance = new API();
LintPathResult result = apiInstance.lintPath(args);
boolean foundWarning = result.getResultsList().stream()
.anyMatch(warning -> warning.contains("Module 'math' imported but unused"));
validateCode
使用 schema 以及 JSON/YAML 数据字符串对代码进行校验。
示例
Java 代码
import com.kcl.api.*;
String code = "schema Person:\n" + " name: str\n" + " age: int\n" + " check:\n"
+ " 0 < age < 120\n";
String data = "{\"name\": \"Alice\", \"age\": 10}";
ValidateCodeArgs args = ValidateCodeArgs.newBuilder().setCode(code).setData(data).setFormat("json").build();
API apiInstance = new API();
ValidateCodeResult result = apiInstance.validateCode(args);
rename
重命名文件中目标符号的所有出现位置。如果文件中包含待重命名的符号, 该 API 会重写文件,并返回发生变更的文件路径。
示例
main.k 的内容为
a = 1
b = a
Java 代码
import com.kcl.api.*;
RenameArgs args = RenameArgs.newBuilder().setPackageRoot(".").setSymbolPath("a")
.addFilePaths("main.k").setNewName("a2").build();
API apiInstance = new API();
RenameResult result = apiInstance.rename(args);
renameCode
重命名目标符号的所有出现位置,并在代码发生变更时返回修改后的代码。 该 API 不会重写文件,而是返回修改后的代码。
示例
Java 代码
import com.kcl.api.*;
API api = new API();
RenameCodeArgs args = RenameCodeArgs.newBuilder().setPackageRoot("/mock/path").setSymbolPath("a")
.putSourceCodes("/mock/path/main.k", "a = 1\nb = a").setNewName("a2").build();
RenameCodeResult result = api.renameCode(args);
test
使用测试参数对 KCL 包执行测试。
示例
Java 代码
import com.kcl.api.*;
API apiInstance = new API();
TestArgs args = TestArgs.newBuilder().addPkgList("/path/to/test/package").build();
TestResult result = apiInstance.test(args);
loadSettingsFiles
加载 kcl.yaml 中定义的配置文件设置。
示例
kcl.yaml 的内容为
kcl_cli_configs:
strict_range_check: true
kcl_options:
- key: key
value: value
Java 代码
import com.kcl.api.*;
API api = new API();
LoadSettingsFilesArgs args = LoadSettingsFilesArgs.newBuilder().addFiles("kcl.yaml")
.build();
LoadSettingsFilesResult result = api.loadSettingsFiles(args);
updateDependencies
下载并更新 kcl.mod 文件中定义的依赖项,并返回外部包的名称与位置列表。
示例
module/kcl.mod 的内容为
[package]
name = "mod_update"
edition = "0.0.1"
version = "0.0.1"
[dependencies]
helloworld = { oci = "oci://ghcr.io/kcl-lang/helloworld", tag = "0.1.0" }
flask = { git = "https://github.com/kcl-lang/flask-demo-kcl-manifests", commit = "ade147b" }
Java 代码
import com.kcl.api.*;
API api = new API();
UpdateDependenciesResult result = api.updateDependencies(
UpdateDependenciesArgs.newBuilder().setManifestPath("module").build());
使用外部依赖调用 execProgram
示例
module/kcl.mod 的内容为
[package]
name = "mod_update"
edition = "0.0.1"
version = "0.0.1"
[dependencies]
helloworld = { oci = "oci://ghcr.io/kcl-lang/helloworld", tag = "0.1.0" }
flask = { git = "https://github.com/kcl-lang/flask-demo-kcl-manifests", commit = "ade147b" }
module/main.k 的内容为
import helloworld
import flask
a = helloworld.The_first_kcl_program
Java 代码
import com.kcl.api.*;
API api = new API();
UpdateDependenciesResult result = api.updateDependencies(
UpdateDependenciesArgs.newBuilder().setManifestPath("./src/test_data/update_dependencies").build());
ExecProgramArgs execArgs = ExecProgramArgs.newBuilder(). addAllExternalPkgs(result.getExternalPkgsList())
.addKFilenameList("./src/test_data/update_dependencies/main.k").build();
ExecProgramResult execResult = api.execProgram(execArgs);
getVersion
返回 KCL 服务的版本信息。
示例
Java 代码
import com.kcl.api.*;
API api = new API();
GetVersionArgs version_args = GetVersionArgs.newBuilder().build();
GetVersionResult result = api.getVersion(version_args);
(具体的 version / checksum / git_sha 值因发布版本而异;
仅需断言其非空即可。)
ping
通过调度器对一个值进行往返传输(round-trip)。
示例
import com.kcl.api.*;
API api = new API();
PingResult result = api.ping(PingArgs.newBuilder().setValue("hello").build());
assert result.getValue().equals("hello");
listMethod
列出底层运行时所支持的 KCL 服务方法名。
示例
import com.kcl.api.*;
API api = new API();
for (String name : api.listMethod().getMethodNameList()) {
System.out.println(name);
}
注意事项
旧的 BuildProgram 和 ExecArtifact RPC 已于 v0.13.0 中从 spec/spec.proto 中移除
(参见 lib commit 815acac);
它们不再被 com.kcl.api.API 调度器识别。如果您之前调用的是
api.buildProgram(...) 或 api.execArtifact(...),请改用 api.execProgram(...)。