From 62c3f042e88dd22fb14664becdbe2e73f497264c Mon Sep 17 00:00:00 2001 From: Joe Lauer Date: Fri, 13 Dec 2024 20:01:02 -0500 Subject: [PATCH] Support for NativeLanguageModel to help build domain-specific models of native words and format templated strings --- README.md | 12 ++ .../com/fizzed/jne/NativeLanguageModel.java | 181 ++++++++++++++++++ .../fizzed/jne/NativeLanguageModelTest.java | 66 +++++++ 3 files changed, 259 insertions(+) create mode 100644 src/main/java/com/fizzed/jne/NativeLanguageModel.java create mode 100644 src/test/java/com/fizzed/jne/NativeLanguageModelTest.java diff --git a/README.md b/README.md index 04dfeaa..8ee4f35 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,18 @@ final JavaHome jdk21 = new JavaHomeFinder() .find(); ``` +To build a native language model to help build native-specific targets, urls, etc. + +```java +final NativeTarget nativeTarget = NativeTarget.detect(); +final NativeLanguageModel nlm = new NativeLanguageModel() + .add("version", "17.0.1") + .add(OperatingSystem.MACOS, "darwin") + .add(HardwareArchitecture.X64, "amd64"); + +final String fileName = nlm.format("restic_{version}_{os}_{arch}.bz2", nativeTarget); +``` + ## Demo To run a demo of a "cat" executable diff --git a/src/main/java/com/fizzed/jne/NativeLanguageModel.java b/src/main/java/com/fizzed/jne/NativeLanguageModel.java new file mode 100644 index 0000000..8b427dd --- /dev/null +++ b/src/main/java/com/fizzed/jne/NativeLanguageModel.java @@ -0,0 +1,181 @@ +package com.fizzed.jne; + +/*- + * #%L + * jne + * %% + * Copyright (C) 2016 - 2024 Fizzed, Inc + * %% + * Licensed 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. + * #L% + */ + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class NativeLanguageModel { + + private final Map values; + private final Map operatingSystems; + private final Map hardwareArchitectures; + private final Map abis; + + public NativeLanguageModel() { + this.values = new HashMap<>(); + this.operatingSystems = new HashMap<>(); + this.hardwareArchitectures = new HashMap<>(); + this.abis = new HashMap<>(); + } + + public NativeLanguageModel add(String from, String to) { + Objects.requireNonNull(from); + Objects.requireNonNull(to); + this.values.put(from, to); + return this; + } + + public NativeLanguageModel add(OperatingSystem from, String to) { + Objects.requireNonNull(from); + Objects.requireNonNull(to); + this.operatingSystems.put(from, to); + return this; + } + + public NativeLanguageModel add(HardwareArchitecture from, String to) { + Objects.requireNonNull(from); + Objects.requireNonNull(to); + this.hardwareArchitectures.put(from, to); + return this; + } + + public NativeLanguageModel add(ABI from, String to) { + Objects.requireNonNull(from); + Objects.requireNonNull(to); + this.abis.put(from, to); + return this; + } + + public String format(String key) { + if (key != null) { + return this.values.get(key); + } + return null; + } + + public String format(OperatingSystem os) { + if (os != null) { + String v = this.operatingSystems.get(os); + if (v == null) { + return os.name().toLowerCase(); + } + return v; + } + return null; + } + + public String format(HardwareArchitecture arch) { + if (arch != null) { + String v = this.hardwareArchitectures.get(arch); + if (v == null) { + return arch.name().toLowerCase(); + } + return v; + } + return null; + } + + public String format(ABI abi) { + if (abi != null) { + String v = this.abis.get(abi); + if (v == null) { + return abi.name().toLowerCase(); + } + return v; + } + return null; + } + + /** + * Template is a strong where {os} {arch} {abi} is replaced with the model's values. + * + * "v17.0.1-{os}-{arch}" + * "v17.0.1-{os}{_?abi}-{arch}" + * "v{version}-{os}{_?abi}-{arch}" + * + * @param template + * @param nativeTarget + * @return + */ + public String format(String template, NativeTarget nativeTarget) { + if (nativeTarget != null) { + return format(template, nativeTarget.getOperatingSystem(), nativeTarget.getHardwareArchitecture(), nativeTarget.getAbi()); + } + return null; + } + + public String format(String template, OperatingSystem os, HardwareArchitecture arch, ABI abi) { + // loop thru template where { marks the start of a replacement + StringBuilder sb = new StringBuilder(); + boolean started = false; + String optFront = null; + String key = null; + for (int i = 0; i < template.length(); i++) { + char c = template.charAt(i); + if (!started) { + if (c == '{') { + started = true; + } else { + sb.append(c); + } + } else { + if (c == '}') { + started = false; + String v = null; + // what was the key that was provided, we'll look it up + if ("os".equals(key)) { + v = this.format(os); + } else if ("arch".equals(key)) { + v = this.format(arch); + } else if ("abi".equals(key)) { + v = this.format(abi); + } else { + v = this.format(key); + if (v == null) { + throw new IllegalArgumentException("Unknown key: " + key + " in template: " + template); + } + } + if (v != null) { + if (optFront != null) { + sb.append(optFront); + } + sb.append(v); + } + optFront = null; + key = null; + } else { + if (c == '?') { + optFront = key; + key = null; + } else { + // we will assume this is part of the key, unless we get a ? + key = key != null ? key + c : "" + c; + } + } + } + } + + return sb.toString(); + } + +} diff --git a/src/test/java/com/fizzed/jne/NativeLanguageModelTest.java b/src/test/java/com/fizzed/jne/NativeLanguageModelTest.java new file mode 100644 index 0000000..8c38e37 --- /dev/null +++ b/src/test/java/com/fizzed/jne/NativeLanguageModelTest.java @@ -0,0 +1,66 @@ +package com.fizzed.jne; + +/*- + * #%L + * jne + * %% + * Copyright (C) 2016 - 2024 Fizzed, Inc + * %% + * Licensed 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. + * #L% + */ + +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +class NativeLanguageModelTest { + + @Test + public void os() { + NativeLanguageModel model = new NativeLanguageModel(); + model.add(OperatingSystem.WINDOWS, "win"); + + assertThat(model.format(OperatingSystem.WINDOWS), is("win")); + assertThat(model.format(OperatingSystem.LINUX), is("linux")); + } + + @Test + public void arch() { + NativeLanguageModel model = new NativeLanguageModel(); + model.add(HardwareArchitecture.X64, "amd64"); + + assertThat(model.format(HardwareArchitecture.X64), is("amd64")); + assertThat(model.format(HardwareArchitecture.ARM64), is("arm64")); + } + + @Test + public void format() { + NativeLanguageModel model = new NativeLanguageModel(); + model.add(OperatingSystem.WINDOWS, "win"); + model.add(HardwareArchitecture.X64, "amd64"); + model.add(HardwareArchitecture.ARM64, "aarch64"); + + assertThat(model.format("v17.0.1-{os}-{arch}", OperatingSystem.WINDOWS, HardwareArchitecture.X64, null), is("v17.0.1-win-amd64")); + assertThat(model.format("v17.0.1-{os}-{arch}", OperatingSystem.LINUX, HardwareArchitecture.X64, null), is("v17.0.1-linux-amd64")); + assertThat(model.format("v17.0.1-{os}-{arch}", OperatingSystem.LINUX, HardwareArchitecture.ARM64, null), is("v17.0.1-linux-aarch64")); + assertThat(model.format("v17.0.1-{os}-{arch}{_?abi}", OperatingSystem.LINUX, HardwareArchitecture.ARM64, null), is("v17.0.1-linux-aarch64")); + assertThat(model.format("v17.0.1-{os}{_?abi}-{arch}", OperatingSystem.LINUX, HardwareArchitecture.ARM64, ABI.MUSL), is("v17.0.1-linux_musl-aarch64")); + + model.add("version", "17.0.1"); + + assertThat(model.format("v{version}-{os}{_?abi}-{arch}", OperatingSystem.LINUX, HardwareArchitecture.ARM64, ABI.MUSL), is("v17.0.1-linux_musl-aarch64")); + } + +}