StarterSetCreateSupport.java
/*
* Copyright © 2026 IKE Network (support@ike.network)
*
* 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.
*/
package network.ike.plugin;
import org.apache.maven.api.Session;
import org.apache.maven.api.plugin.MojoException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* Shared mechanics of the starter-set genesis goals: loading the templates from the
* standards scaffold artifact (the same channel the conformance scaffold consumes —
* one template source, two lifecycle moments) and rendering the plan report the draft
* and publish goals both print.
*/
final class StarterSetCreateSupport {
/** The template directory inside the scaffold artifact. */
static final String TEMPLATE_ROOT = "starter-set/";
private StarterSetCreateSupport() {
}
/**
* Loads the starter-set templates from the standards scaffold zip matching this
* plugin's own version.
*
* @param session the Maven session, for artifact resolution
* @return template-relative path to template text, in zip order
* @throws MojoException if the scaffold artifact cannot be resolved or read
*/
static Map<String, String> loadTemplates(Session session) {
String coordinates = "network.ike.tooling:ike-build-standards:zip:scaffold:" + pluginVersion();
Path zipPath;
try {
zipPath = session.resolveArtifact(session.createArtifactCoordinates(coordinates)).getPath();
} catch (Exception e) {
throw new MojoException("Cannot resolve the standards scaffold artifact "
+ coordinates + " carrying the starter-set templates", e);
}
Map<String, String> templates = new LinkedHashMap<>();
try (ZipFile zip = new ZipFile(zipPath.toFile())) {
java.util.Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if (!entry.isDirectory() && entry.getName().startsWith(TEMPLATE_ROOT)) {
try (InputStream in = zip.getInputStream(entry)) {
templates.put(entry.getName().substring(TEMPLATE_ROOT.length()),
new String(in.readAllBytes(), StandardCharsets.UTF_8));
}
}
}
} catch (IOException e) {
throw new MojoException("Cannot read the starter-set templates from " + zipPath, e);
}
if (templates.isEmpty()) {
throw new MojoException("The scaffold artifact " + coordinates
+ " carries no starter-set templates — standards and plugin versions must match");
}
return templates;
}
/**
* This plugin's own version, read from its build descriptor — the lockstep key for
* resolving the matching standards artifact.
*
* @return the plugin version
* @throws MojoException if the descriptor is unreadable
*/
static String pluginVersion() {
String descriptor = "/META-INF/maven/network.ike.tooling/ike-maven-plugin/pom.properties";
try (InputStream in = StarterSetCreateSupport.class.getResourceAsStream(descriptor)) {
if (in == null) {
throw new MojoException("Plugin build descriptor missing: " + descriptor);
}
Properties properties = new Properties();
properties.load(in);
return properties.getProperty("version");
} catch (IOException e) {
throw new MojoException("Cannot read the plugin build descriptor", e);
}
}
/**
* Renders the genesis plan — identical in draft and publish, so what was reviewed
* is what happens.
*
* @param plan the plan
* @param templates the loaded templates
* @param targetDir the directory the project lands in
* @param mintFresh whether publish will mint a fresh UUID
* @return the report text
*/
static String report(StarterSetPlan plan, Map<String, String> templates,
Path targetDir, boolean mintFresh) {
StringBuilder out = new StringBuilder();
out.append("Starter set: ").append(plan.token("setName")).append('\n');
out.append(" Semantic tag (permanent — in every birth FQN): (")
.append(plan.token("tag")).append(")\n");
out.append(" Set UUID ").append(mintFresh
? "(will be minted at publish): " : "(supplied): ")
.append(plan.token("setUuid")).append('\n');
out.append(" Coordinates: ").append(plan.token("groupId")).append(':')
.append(plan.token("artifactRoot")).append(':')
.append(plan.token("version")).append('\n');
out.append(" Package: ").append(plan.token("basePackage")).append('\n');
out.append(" Directory: ").append(targetDir).append('\n');
out.append(" Files:\n");
for (String templatePath : templates.keySet()) {
out.append(" ").append(plan.targetPath(templatePath)).append('\n');
}
out.append(" Next steps after publish:\n");
out.append(" gh repo create <org>/").append(plan.token("artifactRoot"))
.append(" --public\n");
out.append(" git remote add origin <url> ; git push -u origin main\n");
out.append(" mvn ws:add -Drepo=<url> -Dsubproject=").append(plan.token("artifactRoot"))
.append(" (inside a workspace)\n");
out.append(" mvn install (ledger -> bindings, change set, glossary, KB at ~/Solor/")
.append(plan.token("slug")).append("-kb)\n");
out.append(" Pending curation: stamp author is TinkarTerm#USER until the curator-identity decision.\n");
return out.toString();
}
}