WorkflowUndoConflictException.java
package org.hammer.audio.workflow.collaboration;
import java.io.Serial;
import java.util.List;
import java.util.Objects;
/** Machine-readable semantic conflict raised when a later operation blocks undo or redo. */
public final class WorkflowUndoConflictException extends WorkflowSessionException {
@Serial private static final long serialVersionUID = 1L;
private final String selectedTargetId;
private final List<WorkflowUndoPreview.BlockingOperation> blockers;
/** Creates a conflict tied to one target and its later blockers. */
public WorkflowUndoConflictException(
String sessionId,
String targetOperationId,
List<WorkflowUndoPreview.BlockingOperation> blockingOperations) {
super(
Code.UNDO_CONFLICT,
requireNotBlank(sessionId, "sessionId"),
"Semantic history command is blocked by later operations for target " + targetOperationId);
this.selectedTargetId = requireNotBlank(targetOperationId, "targetOperationId");
this.blockers = List.copyOf(Objects.requireNonNull(blockingOperations, "blockingOperations"));
if (this.blockers.isEmpty()) {
throw new IllegalArgumentException("blockingOperations must not be empty");
}
}
/** Operation whose semantic inverse was requested. */
public String targetOperationId() {
return selectedTargetId;
}
/** Later operations intersecting the target's affected semantic objects. */
public List<WorkflowUndoPreview.BlockingOperation> blockingOperations() {
return blockers;
}
private static String requireNotBlank(String value, String name) {
Objects.requireNonNull(value, name);
if (value.isBlank()) {
throw new IllegalArgumentException(name + " must not be blank");
}
return value;
}
}