//
// CIMMethod.java
//
// The contents of this file are subject to the SNIA Public License Version 1.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.snia.org/resources/openSource.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the 
// License for the specific language governing rights and limitations
// under the License.
//
// The Original Code is CIMMethod.java
// 
// The Initial Developer of the Original Code is David Simons.
//
// Contributor(s):
//
// This source uses the Solaris WBEM APIs version 2.2. 
// Synchronization will be maintained with the Solaris WBEM APIS,
// which are being standardized through the Java Community Process.
//
//
// $Id: CIMMethod.java,v 1.1 2003/07/17 18:32:55 kumpf Exp $
//
// $Log: CIMMethod.java,v $
// Revision 1.1  2003/07/17 18:32:55  kumpf
// HP-BAPU: PEP-64 CIM Client and CIM Listener Java Interface
//
// Revision 1.1.1.1  2001/10/31 18:14:25  karl
// import of SNIA 0_7
//
// Revision 1.8  2000/09/15 16:00:52  davidsi
// - BUG FIX. From Naveen Sharma. Fixed clone method so that name is
//   copied correctly.
//
// Revision 1.7  2000/08/16 05:59:52  shawn
// merge P_TOMCAT31 branch
//
// Revision 1.6.8.1  2000/08/10 00:03:27  shawn
// head merge
//
// Revision 1.6  2000/05/11 10:12:20  davidsi
// - Fixed tabs.
//
// Revision 1.5  2000/05/07 13:29:25  davidsi
// - Modified originClass so that an empty string is used when there is no
//   origin class rather than a null value.
//
// Revision 1.4  2000/05/06 17:04:21  davidsi
// - Modifications to bring classes inline with the SUN WBEM APIs 2.2.
//
// Revision 1.3  2000/04/09 13:19:15  davidsi
// - Switched to StringBuffer (from String) for XML generation.
//
// Revision 1.2  2000/02/13 15:09:07  davidsi
// - Added text to cover re-use of Solaris WBEM APIs.
//
// Revision 1.1.1.1  2000/02/06 16:41:03  davidsi
// Initial version.
//
//
//
package org.snia.wbem.cim;

import java.net.MalformedURLException;
import java.util.Vector;
import org.snia.wbemcmd.xml.XMLNode;
import org.snia.wbemcmd.xml.XMLParameters;

/**
    Creates and instantiates a CIM method, a declaration containing the
    method name, return type, and parameters.  This class defines the 
    operations associated with the manipulation of CIM methods.  Methods
    are provided for the creation, deletion, and manipulation of method
    declarations.
 */

public class CIMMethod extends CIMElement implements Cloneable {
    static private String noOriginClass="";
    //
    // If you add to these, you need to fix the clone() method!
    //
    CIMDataType returnDatatype=null;
    Vector qualifiers=new Vector();
    Vector parameters=new Vector();
    String originClass=noOriginClass;
    String override=null;
    boolean propagated=false;		    // true if method is inheirited
    
    
    /** 
       Creates and instantiates a CIM method. 
     */
    public CIMMethod() {
    }


    /** 
	Creates and instantiates a CIM method with the specified name
	@return String name of the method
     */
    public CIMMethod(String name) {
	setName(name);
    }
 
    /**
        Create a method using a XML definition
        @param node The node containing an XML definition of CIMMethod
     */
    public CIMMethod(org.w3c.dom.Node node) {
	XMLNode qnode=XMLNode.getXMLNode(node);
	    
	if (qnode.getToken()!=XMLNode.XML_ELEMENT_METHOD)
	    throw new java.lang.InstantiationError("Not a method node");
	
	try {
	    XMLNode nextchild;
			 
	    String methodName=qnode.getAttribute(XMLParameters.paramName);
	    String cimType=qnode.getAttribute(XMLParameters.paramTypeAssign);
	    String classOrigin=qnode.getAttribute(XMLParameters.paramClassOrigin);
	    String propagate=qnode.getAttribute(XMLParameters.paramPropagated);

	    //
	    // A method name must be given
	    //
	    if (methodName==null)
		throw new CIMException(CIMException.CIM_ERR_INVALID_PARAMETER,
		    "No method name");
	    //
	    // If no return data type, then method returns nothing (void)
	    //
	    if (cimType!=null)		    
		returnDatatype=CIMDataType.getDataType(cimType);
	    else
		returnDatatype=null;
		
	    setName(methodName);
	    if (classOrigin!=null)
		setOriginClass(classOrigin);
	    if (propagate!=null && propagate.equalsIgnoreCase("true"))
		setPropagated(true);
	    else
		setPropagated(false);
	
	    //
	    // See if there are qualifiers
	    //
	    for(nextchild=qnode.getChild();nextchild!=null && nextchild.getToken()==XMLNode.XML_ELEMENT_QUALIFIER;
		    nextchild=nextchild.getNext())
		qualifiers.addElement(new CIMQualifier(nextchild));

	    //
	    // Handle parameters
	    //
	    for(;nextchild!=null;nextchild=nextchild.getNext()) {
		int paramToken=nextchild.getToken();
		if (paramToken==XMLNode.XML_ELEMENT_PARAMETER ||
		    paramToken==XMLNode.XML_ELEMENT_PARAMETER_REFERENCE ||
		    paramToken==XMLNode.XML_ELEMENT_PARAMETER_ARRAY ||
		    paramToken==XMLNode.XML_ELEMENT_PARAMETER_REFARRAY ) {
		    parameters.addElement(new CIMParameter(nextchild));
		} else {
		    break;
		}
	    }
	    
	} catch (CIMException ce) {
	    throw new java.lang.InstantiationError("Not a method node");
	}
    }
    
    /** 
        setQualifiers - sets the qualifier lists
        @param Vector list of qualifiers
    */
    public void setQualifiers(Vector inQual) {
	qualifiers=inQual;
    }

    /** 
        getQualifiers - returns the list of qualifiers for this method
        @return Vector list of qualifiers
    */
    public Vector getQualifiers() {
	return(qualifiers);
    }

    /** 
        getQualifier - returns the position of the qualifier with
        the given name.
        @param name Name of qualifier to be found.
        @return CIMQualifier specified name qualifier if  found else null.
    */
    public CIMQualifier getQualifier(String name){
	int i;
	int tsize=qualifiers.size();
	for(i=0;i<tsize;i++) {
	    CIMQualifier nq=((CIMQualifier)(qualifiers.elementAt(i)));
	    if (nq.getName().equalsIgnoreCase(name)) {
		return((CIMQualifier)(qualifiers.elementAt(i)));
	    }  
	}
	return(null);
    }

    /** 
        getClassOrigin - Returns the class in which this method
        was defined.
        @return String containing the classOrigin field.
    */
    public String getOriginClass(){
	return(originClass);
    } 

    /** 
        setClassOrigin - Set the ClassOrigin attribute with
        the classname defined on input
        @param classOrigin - String parameter defining the name
        of the class origin
    */
    public void setOriginClass(String ioriginClass) {
	originClass=ioriginClass;
    }
 


    /**
        setParameters Sets the list of parameters for the method
        @param Vector list of input parametrs
     */
    public void setParameters(Vector inParam) {
	parameters=inParam;
    }
 
    /**
        getParameters gets the list of parameters for the method
        @return Vector list of method parametrs
     */
    public Vector getParameters() {
	return(parameters);
    }
 
 
    /** 
        getType  sets the return type of the method
        @param CIMDataType The CIM method type for this method.
    */
    public void setType(CIMDataType type) {
	returnDatatype=type;
    }

    /** 
        getType - gets the method type
        @return CIMDataType The CIM method type for this method.
    */
    public CIMDataType getType() {
	return(returnDatatype);
    }
 
 
    /** 
        getSize - Returns the size of return data type
        @return int size of return data type
    */
    public int getSize() {
	return(returnDatatype.getSize());
    }

    // setSize
    //
    // Sets size of return type
    //
    //public void setSize(int size) {
    // SUNDIFF: not supported - doesn't the data type do it for us?
    //}



    /** 
        sets the name of the overriding method for this method
        @param String name of the overriding method
    */
    public void setOverridingMethod(String om) {
	override=om;
    }

    /** 
        gets the name of the overriding method for this method
        @return String name of the overriding method
    */
    public String getOverridingMethod() {
	return(override);
    }

   /**
       toString returns a String representation of the CIMMethod.
       @return String empty or CIM method string
    */
    public String toString() {
	return("CIMMethod NAME="+getName());
    }


   /**
       toMOF returns a MOF representation of the CIMMethod.
       @return String empty or CIM method string
    */
    public String toMOF() {
	String ret;
	int i;
	
	ret=new String();
	if (qualifiers.size()>0) {
	    ret=ret.concat("[");
	    for(i=0;i<qualifiers.size();i++) {
		CIMQualifier nq=((CIMQualifier)(qualifiers.elementAt(i)));
		if (i>0)
		    ret=ret.concat(",");
		ret=ret.concat(nq.toMOF());
	    }
	    ret=ret.concat("]");
	}

	
        //
        // Viktor Mihajlovski Fixes: Date - 08/13/02
        // Fix for method invocation, result's toMOF() function causes null pointer
        // exception if no result value (e.g. void) given
        //
        if (returnDatatype==null)
            ret=ret.concat("void");
        else
            ret=ret.concat(returnDatatype.toMOF());
	ret=ret.concat(" ");
	ret=ret.concat(getName());
	ret=ret.concat("(");
	
	if (parameters.size()>0) {
	    for(i=0;i<parameters.size();i++) {
		CIMParameter nq=((CIMParameter)(parameters.elementAt(i)));
		if (i>0)
		    ret=ret.concat(",");
		ret=ret.concat(nq.toMOF());
	    }
	}
	ret=ret.concat(");\n");
	return(ret);
    }

    /**
        clone makes a copy of this method including property name, identifier,
        type, origin class, size, value, and qualifiers.
        @return Object cloned object
     */
    public Object clone() {
       CIMMethod meth=new CIMMethod();
	meth.returnDatatype=returnDatatype;
	//
	// Qualifiers have values that change so dup them
	//
	Vector v=new Vector();
	for(int j=0;j<qualifiers.size();j++) {
	    CIMQualifier qual=(CIMQualifier)(qualifiers.elementAt(j));
	    v.addElement(qual.clone());
	}
	meth.setName(getName());
	meth.qualifiers=v;
	meth.parameters=parameters;
	meth.originClass=originClass;
	meth.propagated=propagated;
	return(meth);
    }
    
    /**
        clone makes a copy of this method  including property name, identifier,
        type, origin class, size, value, and qualifiers. However you can control
        the flags includeQualifier and includeClassOrigin.

        @param boolean includeQualifier  TRUE/FALSE
        @param boolean includeClassOrigin TRUE/FALSE
        @return Object cloned object
     */
    public Object clone(boolean includeQualifier,
				  boolean includeClassOrigin) {
	CIMMethod meth=new CIMMethod();
	meth.returnDatatype=returnDatatype;
	//
	// Qualifiers have values that change so dup them
	//
	//
	// Only things that can get changed on a per instance
	// basis get fully dup'd, the rest is just by reference
	//
	if (includeQualifier) {
	    meth.qualifiers=new Vector();
	    for(int i=0;i<qualifiers.size();i++) {
		CIMQualifier cq=(CIMQualifier)(qualifiers.elementAt(i));
		meth.qualifiers.addElement(cq.clone());
	    }
	}
	meth.parameters=parameters;
	meth.originClass=originClass;
	meth.propagated=propagated;
	return(meth);
    }
    

    /**
       toXml returns a string representation of the mehtod - in the
       XML case array identifiers are not included
       @return String XML representation of this method.
     **/
    public String toXml() throws MalformedURLException {
	return(toXml(false,true,true));
    }
    
    /**
       toXml returns a string representation of the mehtod - in the
       XML case array identifiers are not included
       @return String XML representation of this method.
     **/
    public String toXml(boolean localOnly,
			boolean includeQualifiers,
			boolean includeClassOrigin) throws MalformedURLException{
	StringBuffer text;
	String cimName=getName();
	String cimType=null;

	//
	// If only local definitions are required and this is a propagated
	// method then nothing to return
	//
	if (localOnly && propagated)
	    return("");

	if (cimName==null)
	    throw new MalformedURLException("method must have name");
	
	if (returnDatatype!=null)
	    cimType=returnDatatype.toXml();
	
	text=new StringBuffer("<METHOD ");
	if (cimName!=null)
	    text=text.append("NAME=\""+cimName+"\" ");
	if (cimType!=null)
	    text=text.append("TYPE=\""+cimType+"\" ");
	if (includeClassOrigin && originClass!=null)
	    text=text.append("CLASSORIGIN=\""+originClass+"\" ");
	if (propagated==true)
	    text=text.append("PROPAGATED=\"true\" ");
	text=text.append(">");
	
	if (includeQualifiers && qualifiers!=null) {
	    for(int i=0;i<qualifiers.size();i++) {
		CIMQualifier qual=(CIMQualifier)(qualifiers.elementAt(i));
		text=text.append(qual.toXml());
	    }
	}

	for(int j=0;j<parameters.size();j++)
	    text=text.append( ((CIMParameter)(parameters.elementAt(j))).toXml());

	text=text.append("</METHOD>");
	
	return(text.toString());
    }
    

    /** 
        setPropagated - Sets the Propagaged Qualifier 
        @param  boolean True if method is propogated
    */
    public void setPropagated(boolean value) {
	propagated=value;
    }
    
    /** 
        getPropagated - Tests the propogated qualifier
        @return - returns True if method is propogated
     */
    public boolean getPropagated() {
	return(propagated);
    }
}
