/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package	com.netscape.javascript.qa.liveconnect.member;

import com.netscape.javascript.qa.liveconnect.*;
import netscape.javascript.*;

/**
 *	Create JavaScript objects, and set their properties	to a JavaScript object
 *  using eval or call. Verify the values of the properties using getMember.
 *
 *	@see netscape.javascript.JSObject
 *	@see com.netscape.javascript.qa.liveconnect.datatypes.DataTypes_003
 *	@see com.netscape.javascript.qa.liveconnect.datatypes.DataTypes_004
 *
 *	@author	christine m	begle
 */
public class Member_002	extends	LiveConnectTest	{
	public Member_002()	{
		super();
	}

	public static void main( String[] args ) {
		Member_002 test	= new Member_002();
		test.start();
	}

	public void	setupTestEnvironment() {
		super.setupTestEnvironment();
	}

	public void	executeTest() {
		Object data[] =	getDataArray();
		for	( int i	= 0; i < data.length; i++ )	{
			JSObject jsObject =	getJSObject( (Object[]) data[i] );
			setMember( (Object[]) data[i] );
			getMember( jsObject, (Object[]) data[i] );
			removeMember( jsObject, (Object[]) data[i] );
		}
	}
	
	/**
	 *  Create and return a JSObject using data in the data array.
	 *
	 *  @param data Object array containing name of JSObject, and assignment 
	 *  expression
	 *  @return the JSObject
	 */
	public JSObject	getJSObject( Object[] data ) {
	    String constructor = data[0] +" = " + data[1];
	    JSObject theThis = (JSObject) global.eval( constructor );
		return theThis;
	}
	
	/**
	 *  Use JSObject.eval to assign a JavaScript value to a property of a
	 *  JavaScript object.  Verify that the expression returns the value of
	 *  the assignment expression.
	 *
	 *  @param data Object array that has items corresponding to the name of 
	 *  a JSObject, a property of that object, and a JavaScript assignment 
	 *  expression for that property.
	 */
	public void setMember( Object[] data ) {
        Object result = null;	    
	    String evalString = (String) data[0] + "." + (String) data[2] +" = "+ 
	            (String) data[3];
	    try {
    	    result = global.eval( evalString );
        } catch ( Exception e ) {
            exception = evalString + " threw " + e.toString();
            file.exception += exception;
            e.printStackTrace();
        } finally {
            addTestCase(
                "[ " + evalString+ " returned "+result+" ] " +
                result +".equals( " + data[5] +")",
                "true",
                result.equals(data[5]) +"",
                exception );
        }            
    }	    

    /**
     *  Get the value of a JavaScript property.  Check its type and value.
     *
     *  @param theThis JSObject whose property will be checked
     *  @param data Object array containing the name of the JSObject property
     *  and the expected value of that property.
     */
	public void	getMember( JSObject	theThis, Object[] data ) {
		String exception = null;
		String property	 = (String)	data[2];
		Object eValue	 = data[6];
		Object aValue	 = null;
		Class  eClass	 = null;
		Class  aClass	 = null;
		String eType     = (String) data[7];
		String aType     = null;

		try	{
			aValue = theThis.getMember(	property );
	    	if ( aValue	!= null	) {
				eClass = eValue.getClass();
				aClass = aValue.getClass();
				aType  = (String) global.eval( "typeof " + ((String) data[0]) +
				    "." + ((String) data[2]) );
			}
		} catch	( Exception	e )	{
			exception =	theThis	+".getMember( "	+ property + " ) threw " +
				e.toString();
			file.exception += exception;
			e.printStackTrace();
		}  finally {
			if ( aValue	== null	) {
			} else {
				// check the value of the property
				addTestCase(
					"[ getMember returned "	+ aValue +"	] "+
					theThis+".getMember( " +property+" ).equals( "+eValue+"	)",
					"true",
					aValue.equals(eValue) +"",
					exception );

				// check the class of the property
				addTestCase	(
					"[ "+ aValue+".getClass() returned "+aClass.getName()+"] "+
					aClass.getName() +".equals(	" +eClass.getName()	+" )",
					"true",
					aClass.getName().equals(eClass.getName()) +"",
					exception );

                // check the JS type of the property value
                addTestCase(
                    "[ typeof " +aValue +" returned " + aType +" ] "+
                    aType +" .equals( " +eType + " )",
                    "true",
                    aType.equals( eType ) +"",
                    exception );
			}
		}
	}	
	/**
	 *  Delete a JSObject using JSObject.removeMember.  After removing the
	 *  member, check the member's JavaScript value and type.
	 *
	 *
	 
	 *
	 *
	 */
	public void removeMember( JSObject theThis, Object[] data ) {
	    String exception = null;
	    String property = (String) data[2];
	    Object eValue   = data[8];
	    Object aValue   = null;
	    Class  eClass   = null;
	    Class  aClass   = null;
	    String eType    = (String) data[9];
	    String aType    = null;
	    
		try	{
			theThis.removeMember( property );
			aValue = theThis.getMember( property );
	    	if ( aValue	!= null	) {
				eClass = eValue.getClass();
				aClass = aValue.getClass();
				aType  = (String) global.eval( "typeof " + ((String) data[0]) +
				    "." + ((String) data[2]) );
			}
		} catch	( Exception	e )	{
			exception =	theThis	+".getMember( "	+ property + " ) threw " +
				e.toString();
			file.exception += exception;
			e.printStackTrace();
		}  finally {
			if ( aValue	== null	) {
			} else {
				// check the value of the property
				addTestCase(
					"[ after removing, getMember returned "	+ aValue +"	] "+
					theThis+".getMember( " +property+" ).equals( "+eValue+"	)",
					"true",
					aValue.equals(eValue) +"",
					exception );

				// check the class of the property
				addTestCase	(
					"[ after removing, "+ aValue+".getClass() returned "+aClass.getName()+"] "+
					aClass.getName() +".equals(	" +eClass.getName()	+" )",
					"true",
					aClass.getName().equals(eClass.getName()) +"",
					exception );

                // check the JS type of the property value
                addTestCase(
                    "[ after removing, typeof " +aValue +" returned " + aType +" ] "+
                    aType +" .equals( " +eType + " )",
                    "true",
                    aType.equals( eType ) +"",
                    exception );
			}
		}
	    
    }	    
	
	/**
	 *	Get	the	data array,	which is an	object array data arrays, which	are
	 *	also object	arrays.	  The data arrays consist of 8 items
	 *
	 *	<ul>
	 *	<li>	Identifier for JavaScript object
	 *	<li>	Assignment expression to initialize JavaScript object
	 *  <li>    Property of JavaScript object to set / get
	 *  <li>    Value to assign to property
	 *	<li>	Initial value of property
	 *	<li>	Value of property before calling setMember
	 *	<li>	Value returned by setMember
	 *	<li>	Value of property after calling setMember
	 *	<li>	String typeof as determined	by JavaScript
	 *	</ul>
	 *
	 *	To add test	cases to this test,	modify this	method.
	 *
	 *	@return	the	data array.
	 */
	public Object[]	getDataArray() {
		Object d0[]	= {
		    new String( "boo" ),            // 0 identifier
			new	String(	"new Boolean()"),	// 1 assignment expression
			new	String(	"foo" ),			// 2 property
			new	String(	"\"bar\"" ),	    // 3 JavaScript value to assign 
			new	String(	"undefined"	),		// 4 value before assignment
			new String( "bar" ),            // 5 value returned by setter
			new	String(	"bar" ),			// 6 value after assignment
			new	String(	"string"),			// 7 JS typeof value
			new String( "undefined"),       // 8 value after removing
			new String( "undefined")        // 9 typeof after removing
		};
		
		Object d1[] = {
		    new String( "num" ),
		    new String( "new Number(12345)" ),
		    new String( "someProperty" ),
		    new String( ".02134" ),
		    new String( "undefined" ),
		    new Double ( "0.02134"),
		    new Double ( "0.02134"),
		    new String ("number"),
			new String( "undefined"),       // 8 value after removing
			new String( "undefined")        // 9 typeof after removing
		    
        };		    
        
        Object d2[] = {            
            new String( "number" ),
            new String( "Number" ),
            new String( "POSITIVE_INFINITY" ),
            new String( "0" ),
            new Double( Double.POSITIVE_INFINITY ),
            new Double("0" ),
            new Double( Double.POSITIVE_INFINITY ),
            new String( "number" ) ,
            new Double( Double.POSITIVE_INFINITY ),
            new String( "number" ) 
        };            
        
	    Object dataArray[] = { d0, d1, d2 };
		return dataArray;
	}
 }
