Last active
August 10, 2025 12:06
-
-
Save fResult/f1453a711f048295610fbecc4eab4fda to your computer and use it in GitHub Desktop.
Example for the article https://fresult.medium.com/31014f433b49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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