/*
 * Daytona
 * Daytona AI platform API Docs
 *
 * The version of the OpenAPI document: 1.0
 * Contact: support@daytona.com
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */


package io.daytona.api.client.model;

import java.util.Objects;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import io.daytona.api.client.model.BuildInfo;
import io.daytona.api.client.model.SandboxDesiredState;
import io.daytona.api.client.model.SandboxInfo;
import io.daytona.api.client.model.SandboxState;
import io.daytona.api.client.model.SandboxVolume;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import io.daytona.api.client.JSON;

/**
 * Workspace
 */
@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.21.0")
public class Workspace {
  public static final String SERIALIZED_NAME_ID = "id";
  @SerializedName(SERIALIZED_NAME_ID)
  @javax.annotation.Nonnull
  private String id;

  public static final String SERIALIZED_NAME_ORGANIZATION_ID = "organizationId";
  @SerializedName(SERIALIZED_NAME_ORGANIZATION_ID)
  @javax.annotation.Nonnull
  private String organizationId;

  public static final String SERIALIZED_NAME_NAME = "name";
  @SerializedName(SERIALIZED_NAME_NAME)
  @javax.annotation.Nonnull
  private String name;

  public static final String SERIALIZED_NAME_SNAPSHOT = "snapshot";
  @SerializedName(SERIALIZED_NAME_SNAPSHOT)
  @javax.annotation.Nullable
  private String snapshot;

  public static final String SERIALIZED_NAME_USER = "user";
  @SerializedName(SERIALIZED_NAME_USER)
  @javax.annotation.Nonnull
  private String user;

  public static final String SERIALIZED_NAME_ENV = "env";
  @SerializedName(SERIALIZED_NAME_ENV)
  @javax.annotation.Nonnull
  private Map<String, String> env = new HashMap<>();

  public static final String SERIALIZED_NAME_LABELS = "labels";
  @SerializedName(SERIALIZED_NAME_LABELS)
  @javax.annotation.Nonnull
  private Map<String, String> labels = new HashMap<>();

  public static final String SERIALIZED_NAME_PUBLIC = "public";
  @SerializedName(SERIALIZED_NAME_PUBLIC)
  @javax.annotation.Nonnull
  private Boolean _public;

  public static final String SERIALIZED_NAME_NETWORK_BLOCK_ALL = "networkBlockAll";
  @SerializedName(SERIALIZED_NAME_NETWORK_BLOCK_ALL)
  @javax.annotation.Nonnull
  private Boolean networkBlockAll;

  public static final String SERIALIZED_NAME_NETWORK_ALLOW_LIST = "networkAllowList";
  @SerializedName(SERIALIZED_NAME_NETWORK_ALLOW_LIST)
  @javax.annotation.Nullable
  private String networkAllowList;

  public static final String SERIALIZED_NAME_TARGET = "target";
  @SerializedName(SERIALIZED_NAME_TARGET)
  @javax.annotation.Nonnull
  private String target;

  public static final String SERIALIZED_NAME_CPU = "cpu";
  @SerializedName(SERIALIZED_NAME_CPU)
  @javax.annotation.Nonnull
  private BigDecimal cpu;

  public static final String SERIALIZED_NAME_GPU = "gpu";
  @SerializedName(SERIALIZED_NAME_GPU)
  @javax.annotation.Nonnull
  private BigDecimal gpu;

  public static final String SERIALIZED_NAME_MEMORY = "memory";
  @SerializedName(SERIALIZED_NAME_MEMORY)
  @javax.annotation.Nonnull
  private BigDecimal memory;

  public static final String SERIALIZED_NAME_DISK = "disk";
  @SerializedName(SERIALIZED_NAME_DISK)
  @javax.annotation.Nonnull
  private BigDecimal disk;

  public static final String SERIALIZED_NAME_STATE = "state";
  @SerializedName(SERIALIZED_NAME_STATE)
  @javax.annotation.Nullable
  private SandboxState state;

  public static final String SERIALIZED_NAME_DESIRED_STATE = "desiredState";
  @SerializedName(SERIALIZED_NAME_DESIRED_STATE)
  @javax.annotation.Nullable
  private SandboxDesiredState desiredState;

  public static final String SERIALIZED_NAME_ERROR_REASON = "errorReason";
  @SerializedName(SERIALIZED_NAME_ERROR_REASON)
  @javax.annotation.Nullable
  private String errorReason;

  public static final String SERIALIZED_NAME_RECOVERABLE = "recoverable";
  @SerializedName(SERIALIZED_NAME_RECOVERABLE)
  @javax.annotation.Nullable
  private Boolean recoverable;

  /**
   * The state of the backup
   */
  @JsonAdapter(BackupStateEnum.Adapter.class)
  public enum BackupStateEnum {
    NONE("None"),
    
    PENDING("Pending"),
    
    IN_PROGRESS("InProgress"),
    
    COMPLETED("Completed"),
    
    ERROR("Error"),
    
    UNKNOWN_DEFAULT_OPEN_API("unknown_default_open_api");

    private String value;

    BackupStateEnum(String value) {
      this.value = value;
    }

    public String getValue() {
      return value;
    }

    @Override
    public String toString() {
      return String.valueOf(value);
    }

    public static BackupStateEnum fromValue(String value) {
      for (BackupStateEnum b : BackupStateEnum.values()) {
        if (b.value.equals(value)) {
          return b;
        }
      }
      return UNKNOWN_DEFAULT_OPEN_API;
    }

    public static class Adapter extends TypeAdapter<BackupStateEnum> {
      @Override
      public void write(final JsonWriter jsonWriter, final BackupStateEnum enumeration) throws IOException {
        jsonWriter.value(enumeration.getValue());
      }

      @Override
      public BackupStateEnum read(final JsonReader jsonReader) throws IOException {
        String value =  jsonReader.nextString();
        return BackupStateEnum.fromValue(value);
      }
    }

    public static void validateJsonElement(JsonElement jsonElement) throws IOException {
      String value = jsonElement.getAsString();
      BackupStateEnum.fromValue(value);
    }
  }

  public static final String SERIALIZED_NAME_BACKUP_STATE = "backupState";
  @SerializedName(SERIALIZED_NAME_BACKUP_STATE)
  @javax.annotation.Nullable
  private BackupStateEnum backupState;

  public static final String SERIALIZED_NAME_BACKUP_CREATED_AT = "backupCreatedAt";
  @SerializedName(SERIALIZED_NAME_BACKUP_CREATED_AT)
  @javax.annotation.Nullable
  private String backupCreatedAt;

  public static final String SERIALIZED_NAME_AUTO_STOP_INTERVAL = "autoStopInterval";
  @SerializedName(SERIALIZED_NAME_AUTO_STOP_INTERVAL)
  @javax.annotation.Nullable
  private BigDecimal autoStopInterval;

  public static final String SERIALIZED_NAME_AUTO_ARCHIVE_INTERVAL = "autoArchiveInterval";
  @SerializedName(SERIALIZED_NAME_AUTO_ARCHIVE_INTERVAL)
  @javax.annotation.Nullable
  private BigDecimal autoArchiveInterval;

  public static final String SERIALIZED_NAME_AUTO_DELETE_INTERVAL = "autoDeleteInterval";
  @SerializedName(SERIALIZED_NAME_AUTO_DELETE_INTERVAL)
  @javax.annotation.Nullable
  private BigDecimal autoDeleteInterval;

  public static final String SERIALIZED_NAME_VOLUMES = "volumes";
  @SerializedName(SERIALIZED_NAME_VOLUMES)
  @javax.annotation.Nullable
  private List<SandboxVolume> volumes = new ArrayList<>();

  public static final String SERIALIZED_NAME_BUILD_INFO = "buildInfo";
  @SerializedName(SERIALIZED_NAME_BUILD_INFO)
  @javax.annotation.Nullable
  private BuildInfo buildInfo;

  public static final String SERIALIZED_NAME_CREATED_AT = "createdAt";
  @SerializedName(SERIALIZED_NAME_CREATED_AT)
  @javax.annotation.Nullable
  private String createdAt;

  public static final String SERIALIZED_NAME_UPDATED_AT = "updatedAt";
  @SerializedName(SERIALIZED_NAME_UPDATED_AT)
  @javax.annotation.Nullable
  private String updatedAt;

  public static final String SERIALIZED_NAME_LAST_ACTIVITY_AT = "lastActivityAt";
  @SerializedName(SERIALIZED_NAME_LAST_ACTIVITY_AT)
  @javax.annotation.Nullable
  private String lastActivityAt;

  /**
   * The class of the sandbox
   */
  @JsonAdapter(PropertyClassEnum.Adapter.class)
  public enum PropertyClassEnum {
    SMALL("small"),
    
    MEDIUM("medium"),
    
    LARGE("large"),
    
    UNKNOWN_DEFAULT_OPEN_API("unknown_default_open_api");

    private String value;

    PropertyClassEnum(String value) {
      this.value = value;
    }

    public String getValue() {
      return value;
    }

    @Override
    public String toString() {
      return String.valueOf(value);
    }

    public static PropertyClassEnum fromValue(String value) {
      for (PropertyClassEnum b : PropertyClassEnum.values()) {
        if (b.value.equals(value)) {
          return b;
        }
      }
      return UNKNOWN_DEFAULT_OPEN_API;
    }

    public static class Adapter extends TypeAdapter<PropertyClassEnum> {
      @Override
      public void write(final JsonWriter jsonWriter, final PropertyClassEnum enumeration) throws IOException {
        jsonWriter.value(enumeration.getValue());
      }

      @Override
      public PropertyClassEnum read(final JsonReader jsonReader) throws IOException {
        String value =  jsonReader.nextString();
        return PropertyClassEnum.fromValue(value);
      }
    }

    public static void validateJsonElement(JsonElement jsonElement) throws IOException {
      String value = jsonElement.getAsString();
      PropertyClassEnum.fromValue(value);
    }
  }

  public static final String SERIALIZED_NAME_PROPERTY_CLASS = "class";
  @Deprecated
  @SerializedName(SERIALIZED_NAME_PROPERTY_CLASS)
  @javax.annotation.Nullable
  private PropertyClassEnum propertyClass;

  public static final String SERIALIZED_NAME_DAEMON_VERSION = "daemonVersion";
  @SerializedName(SERIALIZED_NAME_DAEMON_VERSION)
  @javax.annotation.Nullable
  private String daemonVersion;

  public static final String SERIALIZED_NAME_RUNNER_ID = "runnerId";
  @SerializedName(SERIALIZED_NAME_RUNNER_ID)
  @javax.annotation.Nullable
  private String runnerId;

  public static final String SERIALIZED_NAME_TOOLBOX_PROXY_URL = "toolboxProxyUrl";
  @SerializedName(SERIALIZED_NAME_TOOLBOX_PROXY_URL)
  @javax.annotation.Nonnull
  private String toolboxProxyUrl;

  public static final String SERIALIZED_NAME_IMAGE = "image";
  @SerializedName(SERIALIZED_NAME_IMAGE)
  @javax.annotation.Nullable
  private String image;

  /**
   * The state of the snapshot
   */
  @JsonAdapter(SnapshotStateEnum.Adapter.class)
  public enum SnapshotStateEnum {
    NONE("None"),
    
    PENDING("Pending"),
    
    IN_PROGRESS("InProgress"),
    
    COMPLETED("Completed"),
    
    ERROR("Error"),
    
    UNKNOWN_DEFAULT_OPEN_API("unknown_default_open_api");

    private String value;

    SnapshotStateEnum(String value) {
      this.value = value;
    }

    public String getValue() {
      return value;
    }

    @Override
    public String toString() {
      return String.valueOf(value);
    }

    public static SnapshotStateEnum fromValue(String value) {
      for (SnapshotStateEnum b : SnapshotStateEnum.values()) {
        if (b.value.equals(value)) {
          return b;
        }
      }
      return UNKNOWN_DEFAULT_OPEN_API;
    }

    public static class Adapter extends TypeAdapter<SnapshotStateEnum> {
      @Override
      public void write(final JsonWriter jsonWriter, final SnapshotStateEnum enumeration) throws IOException {
        jsonWriter.value(enumeration.getValue());
      }

      @Override
      public SnapshotStateEnum read(final JsonReader jsonReader) throws IOException {
        String value =  jsonReader.nextString();
        return SnapshotStateEnum.fromValue(value);
      }
    }

    public static void validateJsonElement(JsonElement jsonElement) throws IOException {
      String value = jsonElement.getAsString();
      SnapshotStateEnum.fromValue(value);
    }
  }

  public static final String SERIALIZED_NAME_SNAPSHOT_STATE = "snapshotState";
  @SerializedName(SERIALIZED_NAME_SNAPSHOT_STATE)
  @javax.annotation.Nullable
  private SnapshotStateEnum snapshotState;

  public static final String SERIALIZED_NAME_SNAPSHOT_CREATED_AT = "snapshotCreatedAt";
  @SerializedName(SERIALIZED_NAME_SNAPSHOT_CREATED_AT)
  @javax.annotation.Nullable
  private String snapshotCreatedAt;

  public static final String SERIALIZED_NAME_INFO = "info";
  @SerializedName(SERIALIZED_NAME_INFO)
  @javax.annotation.Nullable
  private SandboxInfo info;

  public Workspace() {
  }

  public Workspace id(@javax.annotation.Nonnull String id) {
    this.id = id;
    return this;
  }

  /**
   * The ID of the sandbox
   * @return id
   */
  @javax.annotation.Nonnull
  public String getId() {
    return id;
  }

  public void setId(@javax.annotation.Nonnull String id) {
    this.id = id;
  }


  public Workspace organizationId(@javax.annotation.Nonnull String organizationId) {
    this.organizationId = organizationId;
    return this;
  }

  /**
   * The organization ID of the sandbox
   * @return organizationId
   */
  @javax.annotation.Nonnull
  public String getOrganizationId() {
    return organizationId;
  }

  public void setOrganizationId(@javax.annotation.Nonnull String organizationId) {
    this.organizationId = organizationId;
  }


  public Workspace name(@javax.annotation.Nonnull String name) {
    this.name = name;
    return this;
  }

  /**
   * The name of the sandbox
   * @return name
   */
  @javax.annotation.Nonnull
  public String getName() {
    return name;
  }

  public void setName(@javax.annotation.Nonnull String name) {
    this.name = name;
  }


  public Workspace snapshot(@javax.annotation.Nullable String snapshot) {
    this.snapshot = snapshot;
    return this;
  }

  /**
   * The snapshot used for the sandbox
   * @return snapshot
   */
  @javax.annotation.Nullable
  public String getSnapshot() {
    return snapshot;
  }

  public void setSnapshot(@javax.annotation.Nullable String snapshot) {
    this.snapshot = snapshot;
  }


  public Workspace user(@javax.annotation.Nonnull String user) {
    this.user = user;
    return this;
  }

  /**
   * The user associated with the project
   * @return user
   */
  @javax.annotation.Nonnull
  public String getUser() {
    return user;
  }

  public void setUser(@javax.annotation.Nonnull String user) {
    this.user = user;
  }


  public Workspace env(@javax.annotation.Nonnull Map<String, String> env) {
    this.env = env;
    return this;
  }

  public Workspace putEnvItem(String key, String envItem) {
    if (this.env == null) {
      this.env = new HashMap<>();
    }
    this.env.put(key, envItem);
    return this;
  }

  /**
   * Environment variables for the sandbox
   * @return env
   */
  @javax.annotation.Nonnull
  public Map<String, String> getEnv() {
    return env;
  }

  public void setEnv(@javax.annotation.Nonnull Map<String, String> env) {
    this.env = env;
  }


  public Workspace labels(@javax.annotation.Nonnull Map<String, String> labels) {
    this.labels = labels;
    return this;
  }

  public Workspace putLabelsItem(String key, String labelsItem) {
    if (this.labels == null) {
      this.labels = new HashMap<>();
    }
    this.labels.put(key, labelsItem);
    return this;
  }

  /**
   * Labels for the sandbox
   * @return labels
   */
  @javax.annotation.Nonnull
  public Map<String, String> getLabels() {
    return labels;
  }

  public void setLabels(@javax.annotation.Nonnull Map<String, String> labels) {
    this.labels = labels;
  }


  public Workspace _public(@javax.annotation.Nonnull Boolean _public) {
    this._public = _public;
    return this;
  }

  /**
   * Whether the sandbox http preview is public
   * @return _public
   */
  @javax.annotation.Nonnull
  public Boolean getPublic() {
    return _public;
  }

  public void setPublic(@javax.annotation.Nonnull Boolean _public) {
    this._public = _public;
  }


  public Workspace networkBlockAll(@javax.annotation.Nonnull Boolean networkBlockAll) {
    this.networkBlockAll = networkBlockAll;
    return this;
  }

  /**
   * Whether to block all network access for the sandbox
   * @return networkBlockAll
   */
  @javax.annotation.Nonnull
  public Boolean getNetworkBlockAll() {
    return networkBlockAll;
  }

  public void setNetworkBlockAll(@javax.annotation.Nonnull Boolean networkBlockAll) {
    this.networkBlockAll = networkBlockAll;
  }


  public Workspace networkAllowList(@javax.annotation.Nullable String networkAllowList) {
    this.networkAllowList = networkAllowList;
    return this;
  }

  /**
   * Comma-separated list of allowed CIDR network addresses for the sandbox
   * @return networkAllowList
   */
  @javax.annotation.Nullable
  public String getNetworkAllowList() {
    return networkAllowList;
  }

  public void setNetworkAllowList(@javax.annotation.Nullable String networkAllowList) {
    this.networkAllowList = networkAllowList;
  }


  public Workspace target(@javax.annotation.Nonnull String target) {
    this.target = target;
    return this;
  }

  /**
   * The target environment for the sandbox
   * @return target
   */
  @javax.annotation.Nonnull
  public String getTarget() {
    return target;
  }

  public void setTarget(@javax.annotation.Nonnull String target) {
    this.target = target;
  }


  public Workspace cpu(@javax.annotation.Nonnull BigDecimal cpu) {
    this.cpu = cpu;
    return this;
  }

  /**
   * The CPU quota for the sandbox
   * @return cpu
   */
  @javax.annotation.Nonnull
  public BigDecimal getCpu() {
    return cpu;
  }

  public void setCpu(@javax.annotation.Nonnull BigDecimal cpu) {
    this.cpu = cpu;
  }


  public Workspace gpu(@javax.annotation.Nonnull BigDecimal gpu) {
    this.gpu = gpu;
    return this;
  }

  /**
   * The GPU quota for the sandbox
   * @return gpu
   */
  @javax.annotation.Nonnull
  public BigDecimal getGpu() {
    return gpu;
  }

  public void setGpu(@javax.annotation.Nonnull BigDecimal gpu) {
    this.gpu = gpu;
  }


  public Workspace memory(@javax.annotation.Nonnull BigDecimal memory) {
    this.memory = memory;
    return this;
  }

  /**
   * The memory quota for the sandbox
   * @return memory
   */
  @javax.annotation.Nonnull
  public BigDecimal getMemory() {
    return memory;
  }

  public void setMemory(@javax.annotation.Nonnull BigDecimal memory) {
    this.memory = memory;
  }


  public Workspace disk(@javax.annotation.Nonnull BigDecimal disk) {
    this.disk = disk;
    return this;
  }

  /**
   * The disk quota for the sandbox
   * @return disk
   */
  @javax.annotation.Nonnull
  public BigDecimal getDisk() {
    return disk;
  }

  public void setDisk(@javax.annotation.Nonnull BigDecimal disk) {
    this.disk = disk;
  }


  public Workspace state(@javax.annotation.Nullable SandboxState state) {
    this.state = state;
    return this;
  }

  /**
   * The state of the sandbox
   * @return state
   */
  @javax.annotation.Nullable
  public SandboxState getState() {
    return state;
  }

  public void setState(@javax.annotation.Nullable SandboxState state) {
    this.state = state;
  }


  public Workspace desiredState(@javax.annotation.Nullable SandboxDesiredState desiredState) {
    this.desiredState = desiredState;
    return this;
  }

  /**
   * The desired state of the sandbox
   * @return desiredState
   */
  @javax.annotation.Nullable
  public SandboxDesiredState getDesiredState() {
    return desiredState;
  }

  public void setDesiredState(@javax.annotation.Nullable SandboxDesiredState desiredState) {
    this.desiredState = desiredState;
  }


  public Workspace errorReason(@javax.annotation.Nullable String errorReason) {
    this.errorReason = errorReason;
    return this;
  }

  /**
   * The error reason of the sandbox
   * @return errorReason
   */
  @javax.annotation.Nullable
  public String getErrorReason() {
    return errorReason;
  }

  public void setErrorReason(@javax.annotation.Nullable String errorReason) {
    this.errorReason = errorReason;
  }


  public Workspace recoverable(@javax.annotation.Nullable Boolean recoverable) {
    this.recoverable = recoverable;
    return this;
  }

  /**
   * Whether the sandbox error is recoverable.
   * @return recoverable
   */
  @javax.annotation.Nullable
  public Boolean getRecoverable() {
    return recoverable;
  }

  public void setRecoverable(@javax.annotation.Nullable Boolean recoverable) {
    this.recoverable = recoverable;
  }


  public Workspace backupState(@javax.annotation.Nullable BackupStateEnum backupState) {
    this.backupState = backupState;
    return this;
  }

  /**
   * The state of the backup
   * @return backupState
   */
  @javax.annotation.Nullable
  public BackupStateEnum getBackupState() {
    return backupState;
  }

  public void setBackupState(@javax.annotation.Nullable BackupStateEnum backupState) {
    this.backupState = backupState;
  }


  public Workspace backupCreatedAt(@javax.annotation.Nullable String backupCreatedAt) {
    this.backupCreatedAt = backupCreatedAt;
    return this;
  }

  /**
   * The creation timestamp of the last backup
   * @return backupCreatedAt
   */
  @javax.annotation.Nullable
  public String getBackupCreatedAt() {
    return backupCreatedAt;
  }

  public void setBackupCreatedAt(@javax.annotation.Nullable String backupCreatedAt) {
    this.backupCreatedAt = backupCreatedAt;
  }


  public Workspace autoStopInterval(@javax.annotation.Nullable BigDecimal autoStopInterval) {
    this.autoStopInterval = autoStopInterval;
    return this;
  }

  /**
   * Auto-stop interval in minutes (0 means disabled)
   * @return autoStopInterval
   */
  @javax.annotation.Nullable
  public BigDecimal getAutoStopInterval() {
    return autoStopInterval;
  }

  public void setAutoStopInterval(@javax.annotation.Nullable BigDecimal autoStopInterval) {
    this.autoStopInterval = autoStopInterval;
  }


  public Workspace autoArchiveInterval(@javax.annotation.Nullable BigDecimal autoArchiveInterval) {
    this.autoArchiveInterval = autoArchiveInterval;
    return this;
  }

  /**
   * Auto-archive interval in minutes
   * @return autoArchiveInterval
   */
  @javax.annotation.Nullable
  public BigDecimal getAutoArchiveInterval() {
    return autoArchiveInterval;
  }

  public void setAutoArchiveInterval(@javax.annotation.Nullable BigDecimal autoArchiveInterval) {
    this.autoArchiveInterval = autoArchiveInterval;
  }


  public Workspace autoDeleteInterval(@javax.annotation.Nullable BigDecimal autoDeleteInterval) {
    this.autoDeleteInterval = autoDeleteInterval;
    return this;
  }

  /**
   * Auto-delete interval in minutes (negative value means disabled, 0 means delete immediately upon stopping)
   * @return autoDeleteInterval
   */
  @javax.annotation.Nullable
  public BigDecimal getAutoDeleteInterval() {
    return autoDeleteInterval;
  }

  public void setAutoDeleteInterval(@javax.annotation.Nullable BigDecimal autoDeleteInterval) {
    this.autoDeleteInterval = autoDeleteInterval;
  }


  public Workspace volumes(@javax.annotation.Nullable List<SandboxVolume> volumes) {
    this.volumes = volumes;
    return this;
  }

  public Workspace addVolumesItem(SandboxVolume volumesItem) {
    if (this.volumes == null) {
      this.volumes = new ArrayList<>();
    }
    this.volumes.add(volumesItem);
    return this;
  }

  /**
   * Array of volumes attached to the sandbox
   * @return volumes
   */
  @javax.annotation.Nullable
  public List<SandboxVolume> getVolumes() {
    return volumes;
  }

  public void setVolumes(@javax.annotation.Nullable List<SandboxVolume> volumes) {
    this.volumes = volumes;
  }


  public Workspace buildInfo(@javax.annotation.Nullable BuildInfo buildInfo) {
    this.buildInfo = buildInfo;
    return this;
  }

  /**
   * Build information for the sandbox
   * @return buildInfo
   */
  @javax.annotation.Nullable
  public BuildInfo getBuildInfo() {
    return buildInfo;
  }

  public void setBuildInfo(@javax.annotation.Nullable BuildInfo buildInfo) {
    this.buildInfo = buildInfo;
  }


  public Workspace createdAt(@javax.annotation.Nullable String createdAt) {
    this.createdAt = createdAt;
    return this;
  }

  /**
   * The creation timestamp of the sandbox
   * @return createdAt
   */
  @javax.annotation.Nullable
  public String getCreatedAt() {
    return createdAt;
  }

  public void setCreatedAt(@javax.annotation.Nullable String createdAt) {
    this.createdAt = createdAt;
  }


  public Workspace updatedAt(@javax.annotation.Nullable String updatedAt) {
    this.updatedAt = updatedAt;
    return this;
  }

  /**
   * The last update timestamp of the sandbox
   * @return updatedAt
   */
  @javax.annotation.Nullable
  public String getUpdatedAt() {
    return updatedAt;
  }

  public void setUpdatedAt(@javax.annotation.Nullable String updatedAt) {
    this.updatedAt = updatedAt;
  }


  public Workspace lastActivityAt(@javax.annotation.Nullable String lastActivityAt) {
    this.lastActivityAt = lastActivityAt;
    return this;
  }

  /**
   * The last activity timestamp of the sandbox
   * @return lastActivityAt
   */
  @javax.annotation.Nullable
  public String getLastActivityAt() {
    return lastActivityAt;
  }

  public void setLastActivityAt(@javax.annotation.Nullable String lastActivityAt) {
    this.lastActivityAt = lastActivityAt;
  }


  @Deprecated
  public Workspace propertyClass(@javax.annotation.Nullable PropertyClassEnum propertyClass) {
    this.propertyClass = propertyClass;
    return this;
  }

  /**
   * The class of the sandbox
   * @return propertyClass
   * @deprecated
   */
  @Deprecated
  @javax.annotation.Nullable
  public PropertyClassEnum getPropertyClass() {
    return propertyClass;
  }

  @Deprecated
  public void setPropertyClass(@javax.annotation.Nullable PropertyClassEnum propertyClass) {
    this.propertyClass = propertyClass;
  }


  public Workspace daemonVersion(@javax.annotation.Nullable String daemonVersion) {
    this.daemonVersion = daemonVersion;
    return this;
  }

  /**
   * The version of the daemon running in the sandbox
   * @return daemonVersion
   */
  @javax.annotation.Nullable
  public String getDaemonVersion() {
    return daemonVersion;
  }

  public void setDaemonVersion(@javax.annotation.Nullable String daemonVersion) {
    this.daemonVersion = daemonVersion;
  }


  public Workspace runnerId(@javax.annotation.Nullable String runnerId) {
    this.runnerId = runnerId;
    return this;
  }

  /**
   * The runner ID of the sandbox
   * @return runnerId
   */
  @javax.annotation.Nullable
  public String getRunnerId() {
    return runnerId;
  }

  public void setRunnerId(@javax.annotation.Nullable String runnerId) {
    this.runnerId = runnerId;
  }


  public Workspace toolboxProxyUrl(@javax.annotation.Nonnull String toolboxProxyUrl) {
    this.toolboxProxyUrl = toolboxProxyUrl;
    return this;
  }

  /**
   * The toolbox proxy URL for the sandbox
   * @return toolboxProxyUrl
   */
  @javax.annotation.Nonnull
  public String getToolboxProxyUrl() {
    return toolboxProxyUrl;
  }

  public void setToolboxProxyUrl(@javax.annotation.Nonnull String toolboxProxyUrl) {
    this.toolboxProxyUrl = toolboxProxyUrl;
  }


  public Workspace image(@javax.annotation.Nullable String image) {
    this.image = image;
    return this;
  }

  /**
   * The image used for the workspace
   * @return image
   */
  @javax.annotation.Nullable
  public String getImage() {
    return image;
  }

  public void setImage(@javax.annotation.Nullable String image) {
    this.image = image;
  }


  public Workspace snapshotState(@javax.annotation.Nullable SnapshotStateEnum snapshotState) {
    this.snapshotState = snapshotState;
    return this;
  }

  /**
   * The state of the snapshot
   * @return snapshotState
   */
  @javax.annotation.Nullable
  public SnapshotStateEnum getSnapshotState() {
    return snapshotState;
  }

  public void setSnapshotState(@javax.annotation.Nullable SnapshotStateEnum snapshotState) {
    this.snapshotState = snapshotState;
  }


  public Workspace snapshotCreatedAt(@javax.annotation.Nullable String snapshotCreatedAt) {
    this.snapshotCreatedAt = snapshotCreatedAt;
    return this;
  }

  /**
   * The creation timestamp of the last snapshot
   * @return snapshotCreatedAt
   */
  @javax.annotation.Nullable
  public String getSnapshotCreatedAt() {
    return snapshotCreatedAt;
  }

  public void setSnapshotCreatedAt(@javax.annotation.Nullable String snapshotCreatedAt) {
    this.snapshotCreatedAt = snapshotCreatedAt;
  }


  public Workspace info(@javax.annotation.Nullable SandboxInfo info) {
    this.info = info;
    return this;
  }

  /**
   * Additional information about the sandbox
   * @return info
   */
  @javax.annotation.Nullable
  public SandboxInfo getInfo() {
    return info;
  }

  public void setInfo(@javax.annotation.Nullable SandboxInfo info) {
    this.info = info;
  }

  /**
   * A container for additional, undeclared properties.
   * This is a holder for any undeclared properties as specified with
   * the 'additionalProperties' keyword in the OAS document.
   */
  private Map<String, Object> additionalProperties;

  /**
   * Set the additional (undeclared) property with the specified name and value.
   * If the property does not already exist, create it otherwise replace it.
   *
   * @param key name of the property
   * @param value value of the property
   * @return the Workspace instance itself
   */
  public Workspace putAdditionalProperty(String key, Object value) {
    if (this.additionalProperties == null) {
        this.additionalProperties = new HashMap<String, Object>();
    }
    this.additionalProperties.put(key, value);
    return this;
  }

  /**
   * Return the additional (undeclared) property.
   *
   * @return a map of objects
   */
  public Map<String, Object> getAdditionalProperties() {
    return additionalProperties;
  }

  /**
   * Return the additional (undeclared) property with the specified name.
   *
   * @param key name of the property
   * @return an object
   */
  public Object getAdditionalProperty(String key) {
    if (this.additionalProperties == null) {
        return null;
    }
    return this.additionalProperties.get(key);
  }


  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    Workspace workspace = (Workspace) o;
    return Objects.equals(this.id, workspace.id) &&
        Objects.equals(this.organizationId, workspace.organizationId) &&
        Objects.equals(this.name, workspace.name) &&
        Objects.equals(this.snapshot, workspace.snapshot) &&
        Objects.equals(this.user, workspace.user) &&
        Objects.equals(this.env, workspace.env) &&
        Objects.equals(this.labels, workspace.labels) &&
        Objects.equals(this._public, workspace._public) &&
        Objects.equals(this.networkBlockAll, workspace.networkBlockAll) &&
        Objects.equals(this.networkAllowList, workspace.networkAllowList) &&
        Objects.equals(this.target, workspace.target) &&
        Objects.equals(this.cpu, workspace.cpu) &&
        Objects.equals(this.gpu, workspace.gpu) &&
        Objects.equals(this.memory, workspace.memory) &&
        Objects.equals(this.disk, workspace.disk) &&
        Objects.equals(this.state, workspace.state) &&
        Objects.equals(this.desiredState, workspace.desiredState) &&
        Objects.equals(this.errorReason, workspace.errorReason) &&
        Objects.equals(this.recoverable, workspace.recoverable) &&
        Objects.equals(this.backupState, workspace.backupState) &&
        Objects.equals(this.backupCreatedAt, workspace.backupCreatedAt) &&
        Objects.equals(this.autoStopInterval, workspace.autoStopInterval) &&
        Objects.equals(this.autoArchiveInterval, workspace.autoArchiveInterval) &&
        Objects.equals(this.autoDeleteInterval, workspace.autoDeleteInterval) &&
        Objects.equals(this.volumes, workspace.volumes) &&
        Objects.equals(this.buildInfo, workspace.buildInfo) &&
        Objects.equals(this.createdAt, workspace.createdAt) &&
        Objects.equals(this.updatedAt, workspace.updatedAt) &&
        Objects.equals(this.lastActivityAt, workspace.lastActivityAt) &&
        Objects.equals(this.propertyClass, workspace.propertyClass) &&
        Objects.equals(this.daemonVersion, workspace.daemonVersion) &&
        Objects.equals(this.runnerId, workspace.runnerId) &&
        Objects.equals(this.toolboxProxyUrl, workspace.toolboxProxyUrl) &&
        Objects.equals(this.image, workspace.image) &&
        Objects.equals(this.snapshotState, workspace.snapshotState) &&
        Objects.equals(this.snapshotCreatedAt, workspace.snapshotCreatedAt) &&
        Objects.equals(this.info, workspace.info)&&
        Objects.equals(this.additionalProperties, workspace.additionalProperties);
  }

  @Override
  public int hashCode() {
    return Objects.hash(id, organizationId, name, snapshot, user, env, labels, _public, networkBlockAll, networkAllowList, target, cpu, gpu, memory, disk, state, desiredState, errorReason, recoverable, backupState, backupCreatedAt, autoStopInterval, autoArchiveInterval, autoDeleteInterval, volumes, buildInfo, createdAt, updatedAt, lastActivityAt, propertyClass, daemonVersion, runnerId, toolboxProxyUrl, image, snapshotState, snapshotCreatedAt, info, additionalProperties);
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("class Workspace {\n");
    sb.append("    id: ").append(toIndentedString(id)).append("\n");
    sb.append("    organizationId: ").append(toIndentedString(organizationId)).append("\n");
    sb.append("    name: ").append(toIndentedString(name)).append("\n");
    sb.append("    snapshot: ").append(toIndentedString(snapshot)).append("\n");
    sb.append("    user: ").append(toIndentedString(user)).append("\n");
    sb.append("    env: ").append(toIndentedString(env)).append("\n");
    sb.append("    labels: ").append(toIndentedString(labels)).append("\n");
    sb.append("    _public: ").append(toIndentedString(_public)).append("\n");
    sb.append("    networkBlockAll: ").append(toIndentedString(networkBlockAll)).append("\n");
    sb.append("    networkAllowList: ").append(toIndentedString(networkAllowList)).append("\n");
    sb.append("    target: ").append(toIndentedString(target)).append("\n");
    sb.append("    cpu: ").append(toIndentedString(cpu)).append("\n");
    sb.append("    gpu: ").append(toIndentedString(gpu)).append("\n");
    sb.append("    memory: ").append(toIndentedString(memory)).append("\n");
    sb.append("    disk: ").append(toIndentedString(disk)).append("\n");
    sb.append("    state: ").append(toIndentedString(state)).append("\n");
    sb.append("    desiredState: ").append(toIndentedString(desiredState)).append("\n");
    sb.append("    errorReason: ").append(toIndentedString(errorReason)).append("\n");
    sb.append("    recoverable: ").append(toIndentedString(recoverable)).append("\n");
    sb.append("    backupState: ").append(toIndentedString(backupState)).append("\n");
    sb.append("    backupCreatedAt: ").append(toIndentedString(backupCreatedAt)).append("\n");
    sb.append("    autoStopInterval: ").append(toIndentedString(autoStopInterval)).append("\n");
    sb.append("    autoArchiveInterval: ").append(toIndentedString(autoArchiveInterval)).append("\n");
    sb.append("    autoDeleteInterval: ").append(toIndentedString(autoDeleteInterval)).append("\n");
    sb.append("    volumes: ").append(toIndentedString(volumes)).append("\n");
    sb.append("    buildInfo: ").append(toIndentedString(buildInfo)).append("\n");
    sb.append("    createdAt: ").append(toIndentedString(createdAt)).append("\n");
    sb.append("    updatedAt: ").append(toIndentedString(updatedAt)).append("\n");
    sb.append("    lastActivityAt: ").append(toIndentedString(lastActivityAt)).append("\n");
    sb.append("    propertyClass: ").append(toIndentedString(propertyClass)).append("\n");
    sb.append("    daemonVersion: ").append(toIndentedString(daemonVersion)).append("\n");
    sb.append("    runnerId: ").append(toIndentedString(runnerId)).append("\n");
    sb.append("    toolboxProxyUrl: ").append(toIndentedString(toolboxProxyUrl)).append("\n");
    sb.append("    image: ").append(toIndentedString(image)).append("\n");
    sb.append("    snapshotState: ").append(toIndentedString(snapshotState)).append("\n");
    sb.append("    snapshotCreatedAt: ").append(toIndentedString(snapshotCreatedAt)).append("\n");
    sb.append("    info: ").append(toIndentedString(info)).append("\n");
    sb.append("    additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n");
    sb.append("}");
    return sb.toString();
  }

  /**
   * Convert the given object to string with each line indented by 4 spaces
   * (except the first line).
   */
  private String toIndentedString(Object o) {
    return o == null ? "null" : o.toString().replace("\n", "\n    ");
  }


  public static HashSet<String> openapiFields;
  public static HashSet<String> openapiRequiredFields;

  static {
    // a set of all properties/fields (JSON key names)
    openapiFields = new HashSet<String>(Arrays.asList("id", "organizationId", "name", "snapshot", "user", "env", "labels", "public", "networkBlockAll", "networkAllowList", "target", "cpu", "gpu", "memory", "disk", "state", "desiredState", "errorReason", "recoverable", "backupState", "backupCreatedAt", "autoStopInterval", "autoArchiveInterval", "autoDeleteInterval", "volumes", "buildInfo", "createdAt", "updatedAt", "lastActivityAt", "class", "daemonVersion", "runnerId", "toolboxProxyUrl", "image", "snapshotState", "snapshotCreatedAt", "info"));

    // a set of required properties/fields (JSON key names)
    openapiRequiredFields = new HashSet<String>(Arrays.asList("id", "organizationId", "name", "user", "env", "labels", "public", "networkBlockAll", "target", "cpu", "gpu", "memory", "disk", "toolboxProxyUrl"));
  }

  /**
   * Validates the JSON Element and throws an exception if issues found
   *
   * @param jsonElement JSON Element
   * @throws IOException if the JSON Element is invalid with respect to Workspace
   */
  public static void validateJsonElement(JsonElement jsonElement) throws IOException {
      if (jsonElement == null) {
        if (!Workspace.openapiRequiredFields.isEmpty()) { // has required fields but JSON element is null
          throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The required field(s) %s in Workspace is not found in the empty JSON string", Workspace.openapiRequiredFields.toString()));
        }
      }

      // check to make sure all required properties/fields are present in the JSON string
      for (String requiredField : Workspace.openapiRequiredFields) {
        if (jsonElement.getAsJsonObject().get(requiredField) == null) {
          throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The required field `%s` is not found in the JSON string: %s", requiredField, jsonElement.toString()));
        }
      }
        JsonObject jsonObj = jsonElement.getAsJsonObject();
      if (!jsonObj.get("id").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `id` to be a primitive type in the JSON string but got `%s`", jsonObj.get("id").toString()));
      }
      if (!jsonObj.get("organizationId").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `organizationId` to be a primitive type in the JSON string but got `%s`", jsonObj.get("organizationId").toString()));
      }
      if (!jsonObj.get("name").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `name` to be a primitive type in the JSON string but got `%s`", jsonObj.get("name").toString()));
      }
      if ((jsonObj.get("snapshot") != null && !jsonObj.get("snapshot").isJsonNull()) && !jsonObj.get("snapshot").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `snapshot` to be a primitive type in the JSON string but got `%s`", jsonObj.get("snapshot").toString()));
      }
      if (!jsonObj.get("user").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `user` to be a primitive type in the JSON string but got `%s`", jsonObj.get("user").toString()));
      }
      if ((jsonObj.get("networkAllowList") != null && !jsonObj.get("networkAllowList").isJsonNull()) && !jsonObj.get("networkAllowList").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `networkAllowList` to be a primitive type in the JSON string but got `%s`", jsonObj.get("networkAllowList").toString()));
      }
      if (!jsonObj.get("target").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `target` to be a primitive type in the JSON string but got `%s`", jsonObj.get("target").toString()));
      }
      // validate the optional field `state`
      if (jsonObj.get("state") != null && !jsonObj.get("state").isJsonNull()) {
        SandboxState.validateJsonElement(jsonObj.get("state"));
      }
      // validate the optional field `desiredState`
      if (jsonObj.get("desiredState") != null && !jsonObj.get("desiredState").isJsonNull()) {
        SandboxDesiredState.validateJsonElement(jsonObj.get("desiredState"));
      }
      if ((jsonObj.get("errorReason") != null && !jsonObj.get("errorReason").isJsonNull()) && !jsonObj.get("errorReason").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `errorReason` to be a primitive type in the JSON string but got `%s`", jsonObj.get("errorReason").toString()));
      }
      if ((jsonObj.get("backupState") != null && !jsonObj.get("backupState").isJsonNull()) && !jsonObj.get("backupState").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `backupState` to be a primitive type in the JSON string but got `%s`", jsonObj.get("backupState").toString()));
      }
      // validate the optional field `backupState`
      if (jsonObj.get("backupState") != null && !jsonObj.get("backupState").isJsonNull()) {
        BackupStateEnum.validateJsonElement(jsonObj.get("backupState"));
      }
      if ((jsonObj.get("backupCreatedAt") != null && !jsonObj.get("backupCreatedAt").isJsonNull()) && !jsonObj.get("backupCreatedAt").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `backupCreatedAt` to be a primitive type in the JSON string but got `%s`", jsonObj.get("backupCreatedAt").toString()));
      }
      if (jsonObj.get("volumes") != null && !jsonObj.get("volumes").isJsonNull()) {
        JsonArray jsonArrayvolumes = jsonObj.getAsJsonArray("volumes");
        if (jsonArrayvolumes != null) {
          // ensure the json data is an array
          if (!jsonObj.get("volumes").isJsonArray()) {
            throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `volumes` to be an array in the JSON string but got `%s`", jsonObj.get("volumes").toString()));
          }

          // validate the optional field `volumes` (array)
          for (int i = 0; i < jsonArrayvolumes.size(); i++) {
            SandboxVolume.validateJsonElement(jsonArrayvolumes.get(i));
          };
        }
      }
      // validate the optional field `buildInfo`
      if (jsonObj.get("buildInfo") != null && !jsonObj.get("buildInfo").isJsonNull()) {
        BuildInfo.validateJsonElement(jsonObj.get("buildInfo"));
      }
      if ((jsonObj.get("createdAt") != null && !jsonObj.get("createdAt").isJsonNull()) && !jsonObj.get("createdAt").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `createdAt` to be a primitive type in the JSON string but got `%s`", jsonObj.get("createdAt").toString()));
      }
      if ((jsonObj.get("updatedAt") != null && !jsonObj.get("updatedAt").isJsonNull()) && !jsonObj.get("updatedAt").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `updatedAt` to be a primitive type in the JSON string but got `%s`", jsonObj.get("updatedAt").toString()));
      }
      if ((jsonObj.get("lastActivityAt") != null && !jsonObj.get("lastActivityAt").isJsonNull()) && !jsonObj.get("lastActivityAt").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `lastActivityAt` to be a primitive type in the JSON string but got `%s`", jsonObj.get("lastActivityAt").toString()));
      }
      if ((jsonObj.get("class") != null && !jsonObj.get("class").isJsonNull()) && !jsonObj.get("class").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `class` to be a primitive type in the JSON string but got `%s`", jsonObj.get("class").toString()));
      }
      // validate the optional field `class`
      if (jsonObj.get("class") != null && !jsonObj.get("class").isJsonNull()) {
        PropertyClassEnum.validateJsonElement(jsonObj.get("class"));
      }
      if ((jsonObj.get("daemonVersion") != null && !jsonObj.get("daemonVersion").isJsonNull()) && !jsonObj.get("daemonVersion").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `daemonVersion` to be a primitive type in the JSON string but got `%s`", jsonObj.get("daemonVersion").toString()));
      }
      if ((jsonObj.get("runnerId") != null && !jsonObj.get("runnerId").isJsonNull()) && !jsonObj.get("runnerId").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `runnerId` to be a primitive type in the JSON string but got `%s`", jsonObj.get("runnerId").toString()));
      }
      if (!jsonObj.get("toolboxProxyUrl").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `toolboxProxyUrl` to be a primitive type in the JSON string but got `%s`", jsonObj.get("toolboxProxyUrl").toString()));
      }
      if ((jsonObj.get("image") != null && !jsonObj.get("image").isJsonNull()) && !jsonObj.get("image").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `image` to be a primitive type in the JSON string but got `%s`", jsonObj.get("image").toString()));
      }
      if ((jsonObj.get("snapshotState") != null && !jsonObj.get("snapshotState").isJsonNull()) && !jsonObj.get("snapshotState").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `snapshotState` to be a primitive type in the JSON string but got `%s`", jsonObj.get("snapshotState").toString()));
      }
      // validate the optional field `snapshotState`
      if (jsonObj.get("snapshotState") != null && !jsonObj.get("snapshotState").isJsonNull()) {
        SnapshotStateEnum.validateJsonElement(jsonObj.get("snapshotState"));
      }
      if ((jsonObj.get("snapshotCreatedAt") != null && !jsonObj.get("snapshotCreatedAt").isJsonNull()) && !jsonObj.get("snapshotCreatedAt").isJsonPrimitive()) {
        throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "Expected the field `snapshotCreatedAt` to be a primitive type in the JSON string but got `%s`", jsonObj.get("snapshotCreatedAt").toString()));
      }
      // validate the optional field `info`
      if (jsonObj.get("info") != null && !jsonObj.get("info").isJsonNull()) {
        SandboxInfo.validateJsonElement(jsonObj.get("info"));
      }
  }

  public static class CustomTypeAdapterFactory implements TypeAdapterFactory {
    @SuppressWarnings("unchecked")
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
       if (!Workspace.class.isAssignableFrom(type.getRawType())) {
         return null; // this class only serializes 'Workspace' and its subtypes
       }
       final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
       final TypeAdapter<Workspace> thisAdapter
                        = gson.getDelegateAdapter(this, TypeToken.get(Workspace.class));

       return (TypeAdapter<T>) new TypeAdapter<Workspace>() {
           @Override
           public void write(JsonWriter out, Workspace value) throws IOException {
             JsonObject obj = thisAdapter.toJsonTree(value).getAsJsonObject();
             obj.remove("additionalProperties");
             // serialize additional properties
             if (value.getAdditionalProperties() != null) {
               for (Map.Entry<String, Object> entry : value.getAdditionalProperties().entrySet()) {
                 if (entry.getValue() instanceof String)
                   obj.addProperty(entry.getKey(), (String) entry.getValue());
                 else if (entry.getValue() instanceof Number)
                   obj.addProperty(entry.getKey(), (Number) entry.getValue());
                 else if (entry.getValue() instanceof Boolean)
                   obj.addProperty(entry.getKey(), (Boolean) entry.getValue());
                 else if (entry.getValue() instanceof Character)
                   obj.addProperty(entry.getKey(), (Character) entry.getValue());
                 else {
                   JsonElement jsonElement = gson.toJsonTree(entry.getValue());
                   if (jsonElement.isJsonArray()) {
                     obj.add(entry.getKey(), jsonElement.getAsJsonArray());
                   } else {
                     obj.add(entry.getKey(), jsonElement.getAsJsonObject());
                   }
                 }
               }
             }
             elementAdapter.write(out, obj);
           }

           @Override
           public Workspace read(JsonReader in) throws IOException {
             JsonElement jsonElement = elementAdapter.read(in);
             validateJsonElement(jsonElement);
             JsonObject jsonObj = jsonElement.getAsJsonObject();
             // store additional fields in the deserialized instance
             Workspace instance = thisAdapter.fromJsonTree(jsonObj);
             for (Map.Entry<String, JsonElement> entry : jsonObj.entrySet()) {
               if (!openapiFields.contains(entry.getKey())) {
                 if (entry.getValue().isJsonPrimitive()) { // primitive type
                   if (entry.getValue().getAsJsonPrimitive().isString())
                     instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsString());
                   else if (entry.getValue().getAsJsonPrimitive().isNumber())
                     instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsNumber());
                   else if (entry.getValue().getAsJsonPrimitive().isBoolean())
                     instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsBoolean());
                   else
                     throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The field `%s` has unknown primitive type. Value: %s", entry.getKey(), entry.getValue().toString()));
                 } else if (entry.getValue().isJsonArray()) {
                     instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), List.class));
                 } else { // JSON object
                     instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), HashMap.class));
                 }
               }
             }
             return instance;
           }

       }.nullSafe();
    }
  }

  /**
   * Create an instance of Workspace given an JSON string
   *
   * @param jsonString JSON string
   * @return An instance of Workspace
   * @throws IOException if the JSON string is invalid with respect to Workspace
   */
  public static Workspace fromJson(String jsonString) throws IOException {
    return JSON.getGson().fromJson(jsonString, Workspace.class);
  }

  /**
   * Convert an instance of Workspace to an JSON string
   *
   * @return JSON string
   */
  public String toJson() {
    return JSON.getGson().toJson(this);
  }
}

