class JobResult implements Serializable {

	public static JobResult createFrom(AccessExecutionGraph accessExecutionGraph) {
		final JobID jobId = accessExecutionGraph.getJobID();
		final JobStatus jobStatus = accessExecutionGraph.getState();

		checkArgument(
			jobStatus.isGloballyTerminalState(),
			"The job " + accessExecutionGraph.getJobName() + '(' + jobId + ") is not in a globally " +
				"terminal state. It is in state " + jobStatus + '.');

		final JobResult.Builder builder = new JobResult.Builder();
		builder.jobId(jobId);

		builder.applicationStatus(ApplicationStatus.fromJobStatus(accessExecutionGraph.getState()));

		final long netRuntime = accessExecutionGraph.getStatusTimestamp(jobStatus) - accessExecutionGraph.getStatusTimestamp(JobStatus.INITIALIZING);
		// guard against clock changes
		final long guardedNetRuntime = Math.max(netRuntime, 0L);
		builder.netRuntime(guardedNetRuntime);
		builder.accumulatorResults(accessExecutionGraph.getAccumulatorsSerialized());

		if (jobStatus == JobStatus.FAILED) {
			final ErrorInfo errorInfo = accessExecutionGraph.getFailureInfo();
			checkNotNull(errorInfo, "No root cause is found for the job failure.");

			builder.serializedThrowable(errorInfo.getException());
		}

		return builder.build();
	}

	private  JobResult(
			final JobID jobId,
			final ApplicationStatus applicationStatus,
			final Map<String, SerializedValue<OptionalFailure<Object>>> accumulatorResults,
			final long netRuntime,
			@Nullable final SerializedThrowable serializedThrowable);

}