Job.java
// Generated by delombok at Mon Apr 14 16:48:01 UTC 2025
package de.larssh.jes;
import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableSet;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.Set;
import de.larssh.utils.OptionalInts;
import de.larssh.utils.text.Strings;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* Value object containing a jobs status information. Depending on the objects
* creating code not all fields are present.
*
* <p>
* Two {@code Job} objects are equal if their IDs are equal. Therefore two
* objects with the same ID, but different job status (e.g. one older and one
* up-to-date object) are still equal!
*/
@SuppressWarnings({"PMD.DataClass", "PMD.GodClass", "PMD.ShortClassName"})
public class Job {
/**
* The jobs ID, must not be empty
*/
@SuppressWarnings("PMD.ShortVariable")
private final String id;
/**
* The jobs name
*
* <p>
* Depending on the objects creating code this might be a filter value,
* eventually containing {@link JesClient#FILTER_WILDCARD}.
*/
private final String name;
/**
* The jobs status
*/
private final JobStatus status;
/**
* The jobs owner
*
* <p>
* Depending on the objects creating code this might be a filter value,
* eventually containing {@link JesClient#FILTER_WILDCARD}.
*/
private final String owner;
/**
* The jobs JES spool class
*/
private final Optional<String> jesClass;
/**
* The jobs result code
*
* <p>
* This field can be present for {@link JobStatus#OUTPUT} (and
* {@link JobStatus#ALL}) only. It cannot be present as long as
* {@code abendCode} is present.
*/
private final OptionalInt resultCode;
/**
* The jobs abend code
*
* <p>
* This field can be present for {@link JobStatus#OUTPUT} (and
* {@link JobStatus#ALL}) only. It cannot be present as long as
* {@code resultCode} is present.
*/
private final Optional<String> abendCode;
/**
* The jobs flags
*/
private final Set<JobFlag> flags;
/**
* List of job output details
*
* <p>
* Can be filled by
* {@link #createOutput(int, String, int, Optional, Optional, Optional)} and
* must be empty for status other than {@link JobStatus#OUTPUT} (and
* {@link JobStatus#ALL}).
*
* @return list of job outputs
*/
private final List<JobOutput> outputs = new ArrayList<>();
/**
* This constructor creates a {@link Job} in its simplest form. String
* parameters are trimmed and converted to upper case.
*
* @param jobId the jobs ID, must not be empty
* @param name the jobs name or a name filter value
* @param status the jobs status or {@link JobStatus#ALL}
* @param owner the jobs owner or an owner filter value
* @throws JobFieldInconsistentException on inconsistent field value
*/
@SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Fields are initialized prior throwing exceptions")
public Job(final String jobId, final String name, final JobStatus status, final String owner) {
this(jobId, name, status, owner, Optional.empty(), OptionalInt.empty(), Optional.empty());
}
/**
* This constructor creates a {@link Job} allowing to set any field. String
* parameters are trimmed and converted to upper case.
*
* @param jobId the jobs ID, must not be empty
* @param name the jobs name or a name filter value
* @param status the jobs status or {@link JobStatus#ALL}
* @param owner the jobs owner or an owner filter value
* @param jesClass the jobs JES class
* @param resultCode the jobs result code, when held (finished)
* @param abendCode the jobs abend code, when held (finished)
* @param flags the jobs flags
* @throws JobFieldInconsistentException on inconsistent field value
*/
@SuppressWarnings("checkstyle:ParameterNumber")
@SuppressFBWarnings(value = "CT_CONSTRUCTOR_THROW", justification = "Fields are initialized prior throwing exceptions")
public Job(final String jobId, final String name, final JobStatus status, final String owner, final Optional<String> jesClass, final OptionalInt resultCode, final Optional<String> abendCode, final JobFlag... flags) {
id = Strings.toUpperCaseNeutral(jobId.trim());
this.name = Strings.toUpperCaseNeutral(name.trim());
this.status = status;
this.owner = Strings.toUpperCaseNeutral(owner.trim());
this.jesClass = jesClass.map(String::trim).map(Strings::toUpperCaseNeutral);
this.abendCode = abendCode.map(String::trim).map(Strings::toUpperCaseNeutral);
this.resultCode = resultCode;
this.flags = flags.length == 0 ? emptySet() : unmodifiableSet(EnumSet.copyOf(asList(flags)));
validate();
}
/**
* Creates a {@link JobOutput} and adds it to the list of job outputs. Creating
* of job outputs for status other than {@link JobStatus#OUTPUT} (and
* {@link JobStatus#ALL}) is prohibited. String parameters are trimmed and
* converted to upper case.
*
* @param index the job outputs index inside the jobs list of outputs
* (starting at 1)
* @param outputName the job outputs data division name
* @param length the job outputs content length
* @param step the job outputs step name
* @param procedureStep the job outputs procedure step name
* @param outputClass the output class
* @return created job output
* @throws JobFieldInconsistentException on inconsistent field value
*/
public JobOutput createOutput(final int index, final String outputName, final int length, final Optional<String> step, final Optional<String> procedureStep, final Optional<String> outputClass) {
if (getStatus() != JobStatus.OUTPUT && getStatus() != JobStatus.ALL) {
throw new JobFieldInconsistentException("Job outputs for status other than OUTPUT (and ALL) cannot be created. Status: %s", getStatus());
}
final JobOutput output = new JobOutput(this, index, outputName, length, step, procedureStep, outputClass);
outputs.add(output);
return output;
}
/**
* Returns the job output details referenced by {@code name} or
* {@link Optional#empty()} if no such job output exists.
*
* @param name job output name to search for
* @return job output details referenced by {@code name} or
* {@link Optional#empty()} if no such job output exists
*/
public Optional<JobOutput> getOutput(final String name) {
final String trimmedName = name.trim();
return getOutputs().stream().filter(output -> output.getName().equalsIgnoreCase(trimmedName)).findFirst();
}
/**
* List of job output details
*
* <p>
* Can be filled by
* {@link #createOutput(int, String, int, Optional, Optional, Optional)} and
* must be empty for status other than {@link JobStatus#OUTPUT} (and
* {@link JobStatus#ALL}).
*
* @return list of job output details
*/
public List<JobOutput> getOutputs() {
return unmodifiableList(outputs);
}
/**
* Validates fields to be set in a consistent way.
*
* @throws JobFieldInconsistentException on inconsistent field value
*/
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
private void validate() {
if (id.isEmpty()) {
throw new JobFieldInconsistentException("Job ID must be filled, but is empty.");
}
if (jesClass.filter(String::isEmpty).isPresent()) {
throw new JobFieldInconsistentException("JES class must not be empty if present.");
}
if (resultCode.isPresent() && abendCode.isPresent()) {
throw new JobFieldInconsistentException("Result Code and Abend Code must not be present at the same time.");
}
if (OptionalInts.filter(resultCode, r -> r < 0).isPresent()) {
throw new JobFieldInconsistentException("Result Code must not be less than zero.");
}
if (abendCode.filter(String::isEmpty).isPresent()) {
throw new JobFieldInconsistentException("Abend Code must not be empty if present.");
}
if (status != JobStatus.OUTPUT && status != JobStatus.ALL) {
if (resultCode.isPresent()) {
throw new JobFieldInconsistentException(Strings.format("Result Code must not be present for status [%s].", status));
}
if (abendCode.isPresent()) {
throw new JobFieldInconsistentException(Strings.format("Abend Code must not be present for status [%s].", status));
}
}
}
/**
* The jobs ID, must not be empty
*
* @return job id
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public String getId() {
return this.id;
}
/**
* The jobs name
*
* <p>
* Depending on the objects creating code this might be a filter value,
* eventually containing {@link JesClient#FILTER_WILDCARD}.
*
* @return job name
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public String getName() {
return this.name;
}
/**
* The jobs status
*
* @return job status
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public JobStatus getStatus() {
return this.status;
}
/**
* The jobs owner
*
* <p>
* Depending on the objects creating code this might be a filter value,
* eventually containing {@link JesClient#FILTER_WILDCARD}.
*
* @return job owner
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public String getOwner() {
return this.owner;
}
/**
* The jobs JES spool class
*
* @return job class
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public Optional<String> getJesClass() {
return this.jesClass;
}
/**
* The jobs result code
*
* <p>
* This field can be present for {@link JobStatus#OUTPUT} (and
* {@link JobStatus#ALL}) only. It cannot be present as long as
* {@code abendCode} is present.
*
* @return result code
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public OptionalInt getResultCode() {
return this.resultCode;
}
/**
* The jobs abend code
*
* <p>
* This field can be present for {@link JobStatus#OUTPUT} (and
* {@link JobStatus#ALL}) only. It cannot be present as long as
* {@code resultCode} is present.
*
* @return abend code
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public Optional<String> getAbendCode() {
return this.abendCode;
}
/**
* The jobs flags
*
* @return flags
*/
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public Set<JobFlag> getFlags() {
return this.flags;
}
@edu.umd.cs.findbugs.annotations.NonNull
@java.lang.Override
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public java.lang.String toString() {
return "Job(id=" + this.getId() + ", name=" + this.getName() + ", status=" + this.getStatus() + ", owner=" + this.getOwner() + ", jesClass=" + this.getJesClass() + ", resultCode=" + this.getResultCode() + ", abendCode=" + this.getAbendCode() + ", flags=" + this.getFlags() + ", outputs=" + this.getOutputs() + ")";
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public boolean equals(@edu.umd.cs.findbugs.annotations.Nullable final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Job)) return false;
final Job other = (Job) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$id = this.getId();
final java.lang.Object other$id = other.getId();
if (this$id == null ? other$id != null : !this$id.equals(other$id)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
protected boolean canEqual(@edu.umd.cs.findbugs.annotations.Nullable final java.lang.Object other) {
return other instanceof Job;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
@edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
@lombok.Generated
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $id = this.getId();
result = result * PRIME + ($id == null ? 43 : $id.hashCode());
return result;
}
}