// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License 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.cloud.async;

import com.cloud.api.ApiSerializerHelper;

public class AsyncJobResult {
	public static final int STATUS_IN_PROGRESS = 0;
	public static final int STATUS_SUCCEEDED = 1;
	public static final int STATUS_FAILED = 2;
	
	private String cmdOriginator;
	private long jobId;
	private int jobStatus;
	private int processStatus;
	private int resultCode;
	private String result;
	private String uuid;

	public AsyncJobResult(long jobId) {
		this.jobId = jobId;
		jobStatus = STATUS_IN_PROGRESS;
		processStatus = 0;
		resultCode = 0;
		result = "";
	}
	
	public String getCmdOriginator() {
		return cmdOriginator;
	}
	
	public void setCmdOriginator(String cmdOriginator) {
		this.cmdOriginator = cmdOriginator;
	}
	
	public long getJobId() {
		return jobId;
	}
	
	public void setJobId(long jobId) {
		this.jobId = jobId;
	}
	
	public String getUuid() {
		return this.uuid;
	}
	
	public void setUuid(String uuid) {
		this.uuid = uuid;
	}
	
	public int getJobStatus() {
		return jobStatus;
	}
	
	public void setJobStatus(int jobStatus) {
		this.jobStatus = jobStatus;
	}
	
	public int getProcessStatus() {
		return processStatus;
	}
	
	public void setProcessStatus(int processStatus) {
		this.processStatus = processStatus;
	}
	
	public int getResultCode() {
		return resultCode;
	}
	
	public void setResultCode(int resultCode) {
		this.resultCode = resultCode;
	}
	
	public String getResult() {
		return result;
	}
	
	public void setResult(String result) {
		this.result = result;
	}
	
	public Object getResultObject() {
		return ApiSerializerHelper.fromSerializedString(result);
	}
	
	public void setResultObject(Object result) {
		this.result = ApiSerializerHelper.toSerializedStringOld(result);
	}
	
	@Override
    public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("AsyncJobResult {jobId:").append(getJobId());
		sb.append(", jobStatus: ").append(getJobStatus());
		sb.append(", processStatus: ").append(getProcessStatus());
		sb.append(", resultCode: ").append(getResultCode());
		sb.append(", result: ").append(result);
		sb.append("}");
		return sb.toString();
	}
}
