/*
* Copyright 2011-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.amazonaws.services.stepfunctions.builder;
import com.amazonaws.SdkClientException;
import com.amazonaws.services.stepfunctions.builder.internal.Buildable;
import com.amazonaws.services.stepfunctions.builder.internal.DateModule;
import com.amazonaws.services.stepfunctions.builder.internal.PropertyNames;
import com.amazonaws.services.stepfunctions.builder.internal.validation.StateMachineValidator;
import com.amazonaws.services.stepfunctions.builder.states.State;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Represents a StepFunctions state machine. A state machine must have at least one state.
*
* @see https://states-language.net/spec.html#toplevelfields
*/
public final class StateMachine {
private static final ObjectMapper MAPPER = new ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.registerModule(DateModule.INSTANCE);
@JsonProperty(PropertyNames.COMMENT)
private final String comment;
@JsonProperty(PropertyNames.START_AT)
private final String startAt;
@JsonProperty(PropertyNames.TIMEOUT_SECONDS)
private final Integer timeoutSeconds;
@JsonProperty(PropertyNames.STATES)
private final Map states;
@JsonProperty(PropertyNames.VERSION)
private final String version;
private StateMachine(Builder builder) {
this.comment = builder.comment;
this.startAt = builder.startAt;
this.timeoutSeconds = builder.timeoutSeconds;
this.states = Buildable.Utils.build(builder.states);
this.version = builder.version;
}
/**
* @return Human readable description for the state machine.
*/
public String getComment() {
return comment;
}
/**
* @return Name of the state to start execution at.
*/
public String getStartAt() {
return startAt;
}
/**
* @return Timeout, in seconds, that a state machine is allowed to run. If the machine execution runs longer than this timeout
* the execution fails with a {@link ErrorCodes#TIMEOUT} error
*/
public Integer getTimeoutSeconds() {
return timeoutSeconds;
}
/**
* @return The states for this state machine.
*/
public Map getStates() {
return states;
}
/**
* @return The version for this state machine, if explicitly declared.
*/
public String getVersion() {
return version;
}
/**
* @return Compact JSON representation of this StateMachine. May be provided to API calls (see {@link
* com.amazonaws.services.stepfunctions.AWSStepFunctions}).
*/
public String toJson() {
try {
return MAPPER.writeValueAsString(this);
} catch (JsonProcessingException e) {
throw new SdkClientException("Could not serialize state machine.", e);
}
}
/**
* @return Formatted JSON representation of this StateMachine. May be provided to API calls (see {@link
* com.amazonaws.services.stepfunctions.AWSStepFunctions}).
*/
public String toPrettyJson() {
try {
return MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(this);
} catch (JsonProcessingException e) {
throw new SdkClientException("Could not serialize state machine.", e);
}
}
/**
* Deserializes a JSON representation of a state machine into a {@link StateMachine.Builder} .
*
* @param json JSON representing State machine.
* @return Mutable {@link StateMachine.Builder} deserialized from JSON representation.
*/
public static StateMachine.Builder fromJson(String json) {
try {
return MAPPER.readValue(json, StateMachine.Builder.class);
} catch (IOException e) {
throw new SdkClientException(
String.format("Could not deserialize state machine.\n%s", json), e);
}
}
/**
* @return Builder instance to construct a {@link StateMachine}.
*/
public static Builder builder() {
return new Builder();
}
/**
* Builder for a {@link StateMachine}.
*/
public static final class Builder {
@JsonProperty(PropertyNames.COMMENT)
private String comment;
@JsonProperty(PropertyNames.START_AT)
private String startAt;
@JsonProperty(PropertyNames.TIMEOUT_SECONDS)
private Integer timeoutSeconds;
@JsonProperty(PropertyNames.STATES)
private final Map states = new LinkedHashMap();
@JsonProperty(PropertyNames.VERSION)
private String version;
private Builder() {
}
/**
* OPTIONAL. Human readable description for the state machine.
*
* @param comment New comment.
* @return This object for method chaining.
*/
public Builder comment(String comment) {
this.comment = comment;
return this;
}
/**
* REQUIRED. Name of the state to start execution at. Must match a state name provided via {@link #state(String,
* State.Builder)}.
*
* @param startAt Name of starting state.
* @return This object for method chaining.
*/
public Builder startAt(String startAt) {
this.startAt = startAt;
return this;
}
/**
* OPTIONAL. Timeout, in seconds, that a state machine is allowed to run. If the machine execution runs longer than this
* timeout the execution fails with a {@link ErrorCodes#TIMEOUT} error
*
* @param timeoutSeconds Timeout value.
* @return This object for method chaining.
*/
public Builder timeoutSeconds(Integer timeoutSeconds) {
this.timeoutSeconds = timeoutSeconds;
return this;
}
/**
* REQUIRED. Adds a new state to the state machine. A state machine MUST have at least one state.
*
* @param stateName Name of the state
* @param stateBuilder Instance of {@link com.amazonaws.services.stepfunctions.builder.states.State.Builder}. Note that
* the {@link State}
* object is not built until the {@link StateMachine} is built so any modifications on the state
* builder will be reflected in this object.
* @return This object for method chaining.
*/
public Builder state(String stateName, State.Builder stateBuilder) {
this.states.put(stateName, stateBuilder);
return this;
}
/**
* OPTIONAL. Version of the states language, if specified.
*
* @param version Version value.
* @return This object for method chaining.
*/
public Builder version(String version) {
this.version = version;
return this;
}
/**
* @return An immutable {@link StateMachine} object that can be transformed to JSON via {@link StateMachine#toJson()}.
*/
public StateMachine build() {
return new StateMachineValidator(new StateMachine(this)).validate();
}
}
}