WorkflowOperationCommandMetadata.java

package org.hammer.audio.workflow.collaboration.store;

import java.util.Objects;

/**
 * Durable command relation for one accepted semantic operation.
 *
 * @param kind command category
 * @param commandId stable idempotency id of the client/server command
 * @param targetOperationId operation targeted by undo or redo, otherwise {@code null}
 */
public record WorkflowOperationCommandMetadata(
    Kind kind, String commandId, String targetOperationId) {

  /** Durable semantic command categories. */
  public enum Kind {
    NORMAL,
    UNDO,
    REDO
  }

  public WorkflowOperationCommandMetadata {
    Objects.requireNonNull(kind, "kind");
    commandId = requireNotBlank(commandId, "commandId");
    if (kind == Kind.NORMAL) {
      if (targetOperationId != null && !targetOperationId.isBlank()) {
        throw new IllegalArgumentException("normal command must not target an operation");
      }
      targetOperationId = null;
    } else {
      targetOperationId = requireNotBlank(targetOperationId, "targetOperationId");
    }
  }

  /** Metadata for an ordinary forward operation. */
  public static WorkflowOperationCommandMetadata normal(String operationId) {
    return new WorkflowOperationCommandMetadata(Kind.NORMAL, operationId, null);
  }

  /** Metadata for an undo command and its target operation. */
  public static WorkflowOperationCommandMetadata undo(String commandId, String targetOperationId) {
    return new WorkflowOperationCommandMetadata(Kind.UNDO, commandId, targetOperationId);
  }

  /** Metadata for a redo command and its target undo operation. */
  public static WorkflowOperationCommandMetadata redo(
      String commandId, String targetUndoOperationId) {
    return new WorkflowOperationCommandMetadata(Kind.REDO, commandId, targetUndoOperationId);
  }

  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;
  }
}