Skip to content

Instantly share code, notes, and snippets.

@fResult
Last active August 10, 2025 12:06
Show Gist options
  • Select an option

  • Save fResult/f1453a711f048295610fbecc4eab4fda to your computer and use it in GitHub Desktop.

Select an option

Save fResult/f1453a711f048295610fbecc4eab4fda to your computer and use it in GitHub Desktop.
Example for the article https://fresult.medium.com/31014f433b49
import java.time.LocalDateTime;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
class DocumentProcessorApp {
public static void main(String[] args) {
final var trinity = new Submitter("trin123");
final var morpheus = new Approver("morph456");
final var initialDate = LocalDateTime.of(2025, 1, 1, 9, 0);
final var documents = List.of(
new DraftDocument("NEO-001", "Red Pill Budget Allocation", "morpheus", initialDate),
new DraftDocument("WICK-002", "Continental Hotel Marketing Strategy", "winston", initialDate.plusDays(1)),
new DraftDocument("JOHN-003", "High Table HR Policy Update", "charon", initialDate.plusDays(2)),
new PendingDocument("MATRIX-004", "Zion Q1 Resource Report", "dozer", "trinity", initialDate.plusDays(3)),
new PendingDocument("NEO-005", "Machine City Invasion Roadmap", "councillor", "architect", initialDate.plusDays(4)),
new PendingDocument("WICK-006", "Continental Security Protocol", "iosef", "bowery", initialDate.plusDays(5)),
new PendingDocument("SPEED-007", "Bus 2525 Evacuation Plan", "harry", "jack", initialDate.plusDays(6)));
final var documentsByTypeMap =
documents.stream().collect(Collectors.partitioningBy(doc -> doc instanceof DraftDocument));
final var draftDocuments = documentsByTypeMap.get(true);
final var pendingDocumentsForApprove = documentsByTypeMap.get(false).stream().limit(2);
final var pendingDocumentsForReject = documentsByTypeMap.get(false).stream().skip(2);
draftDocuments.stream()
.map(Document.processDocument(trinity, ProcessingAction.SUBMIT))
.forEach(System.out::println);
pendingDocumentsForApprove
.map(Document.processDocument(morpheus, ProcessingAction.APPROVE))
.forEach(System.out::println);
pendingDocumentsForReject
.map(Document.processDocument(morpheus, ProcessingAction.REJECT))
.forEach(System.out::println);
}
}
sealed interface Document
permits DraftDocument, PendingDocument, ApprovedDocument, RejectedDocument {
String id();
String content();
static Function<Document, Document> processDocument(
DocumentOperator operator, ProcessingAction action) {
return doc -> {
final var currentDate = LocalDateTime.now();
return switch (doc) {
case DraftDocument d when operator instanceof Submitter(String submitterId) ->
new PendingDocument(d.id(), d.content(), d.creatorId(), submitterId, currentDate);
case PendingDocument p when operator instanceof Approver(String approverId) ->
approval(p, action, approverId, currentDate);
default ->
throw new IllegalStateException(
String.format("Invalid document transition: %s with role %s",
doc.getClass().getSimpleName(), operator.getClass().getSimpleName()));
};
};
}
private static Document approval(
PendingDocument doc, ProcessingAction action, String approverId, LocalDateTime approvedDate) {
return switch (action) {
case ProcessingAction.APPROVE ->
new ApprovedDocument(doc.id(), doc.content(), doc.creatorId(), doc.submitterId(), approverId, approvedDate);
case ProcessingAction.REJECT ->
new RejectedDocument(doc.id(), doc.content(), doc.creatorId(), doc.submitterId(), approverId, approvedDate);
default ->
throw new IllegalStateException("Cannot submit " + PendingDocument.class.getSimpleName());
};
}
}
record DraftDocument(String id, String content, String creatorId, LocalDateTime createdDate)
implements Document {}
record PendingDocument(String id, String content, String creatorId, String submitterId, LocalDateTime submittedDate)
implements Document {}
record ApprovedDocument(String id, String content, String creatorId, String submitterId, String approverId, LocalDateTime approvedDate)
implements Document {}
record RejectedDocument(String id, String content, String creatorId, String submitterId, String approverId, LocalDateTime rejectedDate)
implements Document {}
sealed interface DocumentOperator permits Submitter, Approver {
String id();
}
record Submitter(String id) implements DocumentOperator {}
record Approver(String id) implements DocumentOperator {}
enum ProcessingAction {
SUBMIT,
APPROVE,
REJECT;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment