WorkflowCollaborationEvent.java
package org.hammer.audio.workflow.collaboration;
import java.time.Instant;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import org.hammer.audio.workflow.WorkflowOperation;
/**
* Committed collaboration event published through an event bus.
*
* @param eventId unique event identifier
* @param sessionId collaboration session identifier
* @param occurredAt event creation timestamp
* @param type event type
* @param actor actor metadata for the event source
* @param payload immutable event payload
*/
public record WorkflowCollaborationEvent(
String eventId,
String sessionId,
Instant occurredAt,
String type,
OperationActor actor,
Map<String, String> payload) {
private static final String TYPE_OPERATION_APPLIED = "WORKFLOW_OPERATION_APPLIED";
private static final String TYPE_UNDO_APPLIED = "WORKFLOW_UNDO_APPLIED";
public WorkflowCollaborationEvent {
Objects.requireNonNull(eventId, "eventId");
Objects.requireNonNull(sessionId, "sessionId");
Objects.requireNonNull(occurredAt, "occurredAt");
Objects.requireNonNull(type, "type");
Objects.requireNonNull(actor, "actor");
Objects.requireNonNull(payload, "payload");
if (eventId.isBlank()) {
throw new IllegalArgumentException("eventId must not be blank");
}
if (sessionId.isBlank()) {
throw new IllegalArgumentException("sessionId must not be blank");
}
if (type.isBlank()) {
throw new IllegalArgumentException("type must not be blank");
}
payload = Map.copyOf(payload);
}
public static WorkflowCollaborationEvent operationApplied(
String sessionId, OperationActor actor, WorkflowOperation operation) {
return new WorkflowCollaborationEvent(
UUID.randomUUID().toString(),
sessionId,
Instant.now(),
TYPE_OPERATION_APPLIED,
actor,
Map.of(
"operationId", operation.operationId(),
"operationType", operation.getClass().getSimpleName(),
"operationAuthor", operation.author()));
}
public static WorkflowCollaborationEvent undoApplied(
String sessionId, OperationActor requestedBy, UndoDetails undoDetails) {
return new WorkflowCollaborationEvent(
UUID.randomUUID().toString(),
sessionId,
Instant.now(),
TYPE_UNDO_APPLIED,
requestedBy,
Map.of(
"undoScope", undoDetails.scope().name(),
"revertedOperationId", undoDetails.revertedOperationId(),
"revertedActorId", undoDetails.revertedActorId(),
"undoOperationId", undoDetails.undoOperationId()));
}
/**
* Details for a shared/personal undo event payload.
*
* @param scope effective undo scope
* @param revertedOperationId operation id that was reverted
* @param revertedActorId actor whose operation was reverted
* @param undoOperationId semantic inverse operation id that was applied
*/
public record UndoDetails(
UndoScope scope, String revertedOperationId, String revertedActorId, String undoOperationId) {
public UndoDetails {
Objects.requireNonNull(scope, "scope");
Objects.requireNonNull(revertedOperationId, "revertedOperationId");
Objects.requireNonNull(revertedActorId, "revertedActorId");
Objects.requireNonNull(undoOperationId, "undoOperationId");
}
}
}