IkeGoal.java

package network.ike.plugin;

import network.ike.plugin.support.GoalRef;
import org.apache.maven.api.plugin.Mojo;

import java.util.Optional;

/**
 * Compile-time identity for every {@code ike:*} goal in this plugin. Each
 * value wraps the bare goal name, the mojo class that implements it, and
 * a short human description. Draft/publish siblings expose each other
 * through {@link #pair()}.
 *
 * <p>Parallels {@code network.ike.plugin.ws.WsGoal} in the ws plugin.
 * Callers that invoke ike goals from Java — for subprocess exec, for
 * report identification, for javadoc examples that survive a rename —
 * should reference these enum values rather than string literals.
 *
 * <p>See issue #166.
 */
public enum IkeGoal implements GoalRef {

    /** {@code ike:cascade-export} — export the release cascade topology for CI. */
    CASCADE_EXPORT("cascade-export", IkeCascadeExportMojo.class,
            "Export the foundation release cascade topology as JSON "
                    + "or .properties so a CI meta-runner can generate "
                    + "build-chain edges from release-cascade.yaml "
                    + "instead of hand-wiring them."),
    /** {@code ike:codesign-natives} — sign macOS native binaries in a runtime image. */
    CODESIGN_NATIVES("codesign-natives", CodesignNativesMojo.class,
            "Sign macOS native libraries and executables inside a runtime image."),
    /** {@code ike:codesign-pkg} — sign a {@code .pkg} installer with Developer ID. */
    CODESIGN_PKG("codesign-pkg", CodesignPkgMojo.class,
            "Sign a .pkg installer with a Developer ID Installer certificate."),
    /** {@code ike:env} — print runtime environment / terminal diagnostics. */
    ENV("env", IkeEnvMojo.class,
            "Print runtime environment diagnostics — terminal/console "
                    + "capability, stdin, and relevant system properties. "
                    + "Run from both IntelliJ's Maven tool window and the "
                    + "Terminal tool window to compare (ike-issues#385)."),
    /** {@code ike:generate-bom} — generate the auto-managed BOM. */
    GENERATE_BOM("generate-bom", GenerateBomMojo.class,
            "Generate the auto-managed BOM from the current dependencyManagement."),
    /** {@code ike:help} — list {@code ike:*} goals from the plugin descriptor. */
    HELP("help", IkeHelpMojo.class,
            "List ike:* goals discovered from the plugin descriptor."),
    /** {@code ike:inject-breadcrumb} — inject breadcrumbs into rendered HTML. */
    INJECT_BREADCRUMB("inject-breadcrumb", InjectBreadcrumbMojo.class,
            "Inject breadcrumb navigation into rendered HTML."),
    /** {@code ike:jpackage-props} — emit jpackage properties from reactor config. */
    JPACKAGE_PROPS("jpackage-props", JpackagePropsMojo.class,
            "Emit jpackage properties files from reactor configuration."),
    /** {@code ike:notarize} — submit a {@code .pkg}/{@code .app} to Apple notary. */
    NOTARIZE("notarize", NotarizeMojo.class,
            "Submit a .pkg or .app to Apple notary service and staple the ticket."),
    /** {@code ike:release-draft} — preview releasing the current project. */
    RELEASE_DRAFT("release-draft", ReleaseDraftMojo.class,
            "Preview releasing the current project."),
    /** {@code ike:release-publish} — release the current project (tag + publish). */
    RELEASE_PUBLISH("release-publish", ReleasePublishMojo.class,
            "Release the current project (tag + publish)."),
    /** {@code ike:release-cascade} — release the whole foundation cascade in order. */
    RELEASE_CASCADE("release-cascade", IkeReleaseCascadeMojo.class,
            "Walk the decentralized release cascade assembled from "
                    + "the per-project release-cascade.yaml manifests "
                    + "and run ike:release-publish on every foundation "
                    + "repo that has unreleased changes, in topological "
                    + "order."),
    /** {@code ike:rename} — rename output files to a canonical pattern. */
    RENAME("rename", RenameMojo.class,
            "Rename output files to a canonical pattern."),
    /** {@code ike:built-with} — generate a Built With page from the SBOM and a curated supplement (#336). */
    BUILT_WITH("built-with", BuiltWithMojo.class,
            "Generate a curated Built-With page from the CycloneDX "
                    + "SBOM and an optional project-wide supplement "
                    + "YAML. Replaces the legacy 'Third-Party Notices' "
                    + "naming with a friendlier scannable label and "
                    + "supports per-module rendering by walking up "
                    + "the filesystem to find the reactor's "
                    + "supplement.yaml."),
    /** {@code ike:render-sbom-viewer} — generate dependencies.adoc from the CycloneDX SBOM (#341). */
    RENDER_SBOM_VIEWER("render-sbom-viewer", RenderSbomViewerMojo.class,
            "Generate a Web-friendly dependencies.adoc page from "
                    + "the CycloneDX SBOM with a sortable component "
                    + "table. Maven Site renders it to "
                    + "dependencies.html, replacing the auto-"
                    + "generated dependency report."),
    /** {@code ike:render-spdx-licenses} — generate licenses.adoc from the CycloneDX SBOM (#335). */
    RENDER_SPDX_LICENSES("render-spdx-licenses", RenderSpdxLicensesMojo.class,
            "Generate an SPDX-grouped licenses.adoc page from the "
                    + "CycloneDX SBOM. Maven Site renders it to "
                    + "licenses.html with the project skin chrome."),
    /** {@code ike:scaffold-draft} — preview ike-build-standards scaffold changes. */
    SCAFFOLD_DRAFT("scaffold-draft", ScaffoldDraftMojo.class,
            "Preview what ike:scaffold-publish would apply from the "
                    + "ike-build-standards scaffold."),
    /** {@code ike:scaffold-publish} — apply the scaffold to disk. */
    SCAFFOLD_PUBLISH("scaffold-publish", ScaffoldPublishMojo.class,
            "Apply the ike-build-standards scaffold to disk and "
                    + "update per-project and per-user lockfiles."),
    /** {@code ike:scaffold-revert} — undo a previous scaffold-publish. */
    SCAFFOLD_REVERT("scaffold-revert", ScaffoldRevertMojo.class,
            "Undo a previous ike:scaffold-publish, leaving "
                    + "user-edited files alone."),
    /** {@code ike:site-draft} — report deployed-site drift (#398). */
    SITE_DRAFT("site-draft", IkeSiteDraftMojo.class,
            "Report drift in deployed-site state — version on "
                    + "server vs current project version, landing-page "
                    + "registration status — with copy-paste opt-out "
                    + "commands inline."),
    /** {@code ike:site-publish} — apply deployed-site convergence (#398). */
    SITE_PUBLISH("site-publish", IkeSitePublishMojo.class,
            "Deploy the current version to gh-pages and update the "
                    + "IKE Network landing page registration. Flags: "
                    + "-DupdateSite=false, -DupdateRegistration=false, "
                    + "-Dsite=removed (uninstall: deregister + cleanup)."),
    /** {@code ike:setup} — one-time setup for an IKE development machine. */
    SETUP("setup", SetupMojo.class,
            "One-time setup for an IKE development machine."),
    /** {@code ike:unpack-zip} — unpack a zip artifact into a target directory. */
    UNPACK_ZIP("unpack-zip", UnpackZipMojo.class,
            "Unpack a zip artifact into a target directory."),
    /** {@code ike:verify-release-published} — verify all post-release publication targets (#374). */
    VERIFY_RELEASE_PUBLISHED("verify-release-published",
            VerifyReleasePublishedMojo.class,
            "Verify all post-release publication targets are "
                    + "reachable for the current project + version: "
                    + "site (current/versioned/latest), org-site "
                    + "landing, Nexus artifact, GitHub release tag. "
                    + "Read-only; exits non-zero on any failure.");

    /** Shared {@code ike:} prefix for all goals in this plugin. */
    public static final String PLUGIN_PREFIX = "ike";

    private static final String DRAFT_SUFFIX = "-draft";
    private static final String PUBLISH_SUFFIX = "-publish";

    private final String goalName;
    private final Class<? extends Mojo> mojoClass;
    private final String description;

    IkeGoal(String goalName,
            Class<? extends Mojo> mojoClass,
            String description) {
        this.goalName = goalName;
        this.mojoClass = mojoClass;
        this.description = description;
    }

    /**
     * The bare goal name as it appears in {@code @Mojo(name = ...)}.
     *
     * @return the bare goal name
     */
    @Override
    public String goalName() {
        return goalName;
    }

    /**
     * The {@code ike} plugin prefix — shared by every goal in this enum.
     *
     * @return {@link #PLUGIN_PREFIX}
     */
    @Override
    public String pluginPrefix() {
        return PLUGIN_PREFIX;
    }

    /**
     * The fully-qualified goal invocation, e.g. {@code "ike:release-publish"}.
     *
     * @return the fully-qualified goal invocation
     */
    @Override
    public String qualified() {
        return PLUGIN_PREFIX + ":" + goalName;
    }

    /**
     * The mojo class that implements this goal.
     *
     * @return the mojo class
     */
    public Class<? extends Mojo> mojoClass() {
        return mojoClass;
    }

    /**
     * One-line human description of what this goal does.
     *
     * @return the human description
     */
    @Override
    public String description() {
        return description;
    }

    /**
     * True if this is the {@code -draft} counterpart of a draft/publish pair.
     *
     * @return {@code true} when this goal is a draft variant
     */
    public boolean isDraft() {
        return goalName.endsWith(DRAFT_SUFFIX);
    }

    /**
     * True if this is the {@code -publish} counterpart of a draft/publish pair.
     *
     * @return {@code true} when this goal is a publish variant
     */
    public boolean isPublish() {
        return goalName.endsWith(PUBLISH_SUFFIX);
    }

    /**
     * The paired draft/publish sibling, if this goal belongs to a pair.
     *
     * @return the sibling goal, or empty if this goal is a singleton
     */
    public Optional<IkeGoal> pair() {
        if (isDraft()) {
            return byName(stripSuffix(goalName, DRAFT_SUFFIX) + PUBLISH_SUFFIX);
        }
        if (isPublish()) {
            return byName(stripSuffix(goalName, PUBLISH_SUFFIX) + DRAFT_SUFFIX);
        }
        return Optional.empty();
    }

    /**
     * Look up a goal by its bare name (e.g. {@code "release-publish"}).
     *
     * @param goalName the bare goal name, without the {@code ike:} prefix
     * @return the matching goal, or empty if none
     */
    public static Optional<IkeGoal> byName(String goalName) {
        for (IkeGoal g : values()) {
            if (g.goalName.equals(goalName)) return Optional.of(g);
        }
        return Optional.empty();
    }

    private static String stripSuffix(String s, String suffix) {
        return s.substring(0, s.length() - suffix.length());
    }
}