// 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.api.doc;

import java.util.ArrayList;

public class Command {
	
	private String name;
	private String description;
    private String usage;
	private boolean isAsync;
	private String sinceVersion = null;
	private ArrayList<Argument> request;
	private ArrayList<Argument> response;
	
	public Command(String name, String description) {
		this.name = name;
		this.description = description;
	}
	
	public Command() {}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public ArrayList<Argument> getRequest() {
		return request;
	}

	public void setRequest(ArrayList<Argument> request) {
		this.request = request;
	}

	public ArrayList<Argument> getResponse() {
		return response;
	}

	public void setResponse(ArrayList<Argument> response) {
		this.response = response;
	}
	
	public boolean isAsync() {
        return isAsync;
    }

    public void setAsync(boolean isAsync) {
        this.isAsync = isAsync;
    }

	public String getSinceVersion() {
		return sinceVersion;
	}

	public void setSinceVersion(String sinceVersion) {
		this.sinceVersion = sinceVersion;
	}
	
    public Argument getReqArgByName(String name){
		for (Argument a : this.getRequest()) {
			if (a.getName().equals(name)) {
                return a;
            }
		}
		return null;
	}
	
	public Argument getResArgByName(String name){
		for (Argument a : this.getResponse()) {
			if (a.getName().equals(name)) {
                return a;
            }
		}
		return null;
	}
	
	public String getUsage() {
		return usage;
	}

	public void setUsage(String usage) {
		this.usage = usage;
	}
}
