A generated paragraph can look finished even when the generation stopped early. Before passing AI text into a publishing workflow, inspect a normalized completion state as well as the text. This example creates a small Java boundary that accepts only a completed, nonblank result.
Prerequisites are JDK 21 and a terminal. No dependencies or model server are needed. The enum below is an application-owned contract, not a list of fields or status values promised by a particular AI provider. Your existing client adapter must map its documented response into this contract. Unrecognized outcomes should remain UNKNOWN.
Complete example
Save as CompletionGate.java:
public class CompletionGate {
enum State { COMPLETE, TRUNCATED, REFUSED, TOOL_PENDING, UNKNOWN }
record Result(State state, String text) {}
static String publishable(Result result) {
if (result == null || result.state() != State.COMPLETE ||
result.text() == null || result.text().isBlank()) {
throw new IllegalArgumentException("review required");
}
return result.text();
}
public static void main(String[] args) {
if (!publishable(new Result(State.COMPLETE, "Ready")).equals("Ready"))
throw new AssertionError();
int rejected = 0;
for (Result r : new Result[] {
new Result(State.TRUNCATED, "Looks finished."),
new Result(State.REFUSED, "No"),
new Result(State.TOOL_PENDING, ""),
new Result(State.UNKNOWN, "Text"),
new Result(null, "Text"), new Result(State.COMPLETE, " "),
new Result(State.COMPLETE, null), null }) {
try { publishable(r); throw new AssertionError("accepted"); }
catch (IllegalArgumentException expected) { rejected++; }
}
System.out.println("accepted=1 rejected=" + rejected);
}
}
Run
java CompletionGate.java
Expected output:
accepted=1 rejected=8
The most useful fixture is the truncated result containing Looks finished.. Its punctuation does not override the state. A pending tool operation is also rejected, because intermediate output should not enter the same route as a final answer. Null states fail the equality check without needing an enum conversion.
The function returns the original text without trimming or rewriting it. Validation and content transformation are separate decisions: callers can preserve meaningful formatting while still rejecting blank results.
Integration and edge cases
Place this gate after response decoding and provider-specific status mapping. A transport failure should not become a successful result with an empty string. For streaming clients, wait until the terminal event has been processed before constructing the normalized result; partial text alone is insufficient.
A completed result can still be incorrect, unsupported or unsuitable for publication. Add your content checks after this mechanical gate. Keep refusal handling and retry policies explicit rather than repeatedly retrying every rejected result. A pending tool operation should follow the application's authorized tool workflow.
If valid output is unexpectedly rejected, inspect the adapter's state mapping using a sanitized fixture. The executable tests cover the local gate only. They do not test provider status interpretation, streaming assembly, factual accuracy or any real generation.
Primary references
See Java 21 documentation for enum types. Explore more Java tutorials and AI integration examples.