// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
// 
// Automatically generated by addcopyright.py at 04/03/2012
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();
	}
}
