package edu.calpoly.cpe205.fetter; import java.lang.reflect.*; import javax.swing.*; import java.util.*; import java.io.*; import java.lang.reflect.*; import java.lang.*; import java.awt.*; import javax.swing.event.*; import java.awt.event.*; /** * ETAMainModel stores the references to all the data of the ETA program. * This data includes the reference to the Main Test Object as well as * the Main Test Class. It will store a Collection of all the methods * and fields of the Main Test Class. It will also store a Collection of * of all the Test Object Items created by the user. It will store a * Collection of returned Objects that are returned from method calls * issued by the user * @see MethodData * @see FieldData * @see ParameterData * @see ReturnedData */ // Author: Mike Power // Version History: // Nov 19, 2000 - comments/pseudocode added // Nov 30, 2000 - (Michael Hebron) fixed class description so it shows up // in javadocs // Jan 17, 2001 - (Wes Strickland) added stubs for Stage One release // Jan 31, 2001 - (Apel Yahinian) implemented InstantiateClass() method // Feb 28, 2001 - (Wes Strickland) added code for Stage Three (code already complete) public class ETAMainModel { /** * Constructs a new ETAMainModel. *
* Pre-conditions: none
* Post-conditions: listeners is non-null
* methods is non-null
* fields is non-null
* returnedObjects is non-null
* parameterObjects is non-null
*/
public ETAMainModel()
{
//SET listeners to NEW LinkedList
//listeners = new LinkedList();
//SET methods to NEW LinkedList
methods = new LinkedList();
//SET fields to NEW LinkedList
fields = new LinkedList();
pool.addParameterListener(new ParameterPoolListener());
pool.addReturnListener(new ReturnedPoolListener());
}
/**
* Removes from parameter Collection and informs all listeners that data
* has been removed
* Post-conditions: data has been removed from Collection parameters
*/
public void removeParameterData(ParameterData data)
{
//CALL removeParameterData of pool with data
pool.removeParameterData(data);
}
/**
* Removes from parameter collection and informs all listeners that data
* has been removed
*
* Post-conditions: data has been removed from Collection returnedListeners */ public void removeReturnedData(ReturnedData data) { //CALL removeReturnedData of pool with data pool.removeReturnedData(data); } /** * Displays the fields of the object *
* Pre-condition: none
* Post-condition: none
* @param obj object to be inspected
* @param description description of object being inpected
* @param editable boolean stating whether the user will be able to edit the object or not
*/
public void inspect(Object obj, String description, boolean editable)
{
//CALL inspect of inspect with obj and editable
//CALL setVisible on inspect with true
Assert.preCondition(obj != null, "Can't inspect null");
inspect = new ObjectInspector(view);
inspect.inspect(obj, description, editable);
inspect.setVisible(true);
}
/**
*Sets the class that the user wants to test
*
*Pre-conditions: none
*Post-conditions: none
*@param classToLoad the fully quallified class name that the user wants
*to test
*@return indicates if the classToLoaded loaded without error
*/
public boolean setMainTestClass(String classToLoad)
{
//CALL getClass on this returns thisClass
//CALL getClassLoader on thisClass returns loader
ClassLoader load = null; //A classloader that will be used to load classes with strings
boolean result; //indicates the result of the call to the class loader
load = this.getClass().getClassLoader();
result = false;
//TRY
//CALL loadClass on loader with parameter classToLoad returns
//loadedClass throws ClassNotFoundException
//CALL setMainTestClass with parameter loadedClass
//set result to true
//ENDTRY
try
{
Class newWorkingClass = null; //the class that is to be loaded in by the class loader
newWorkingClass = load.loadClass(classToLoad);
setMainTestClass(newWorkingClass);
result = true;
//CATCH ClassNotFoundException
//set result to false
//ENDCATCH
} catch(ClassNotFoundException exc)
{
ETA.out.println(classToLoad + " not found in classpath");
result = false;
}
//RETURN result
return result;
}
/**
*Sets the class that the user wants to test
*
*Pre-conditions: the view has been set
*Post-conditions: mainTestObject is null
*
*@param the class that the user wants to load and test */ public void setMainTestClass(Class classToLoad) { //SET workingClass to classToLoad mainTestClass = classToLoad; //CALL clearFields on view view.clearFields(); //CALL clearMethods on view view.clearMethods(); //CALL clearPreview on view view.clearPreview(); //CALL populateView with classToLoad populateView(classToLoad); //CALL enableMainTest on view with false view.enableMainTest(false); //SET mainTestObject to null mainTestObject = null; //RETURN true return; } /** * Populates the View with all the methods and fields declared in * declaredClass. Determines the super class and super interfaces of * declaredClass and class popluateView for each. *
* Pre-conditions: the view has been set
* Post-conditions: the view is updated with all declared methods and
* fields of declaredClass
* @param declaredClass the Class that parsed to populate the view with
* methods and fields
*/
protected void populateView(Class declaredClass)
{
Method[] methods = null; //All the declared methods of "declaredClass"
Field[] fields = null; //All the declared fields of "declaredClass"
Class[] interfaces = null; //All the declared interfaces of "declaredClass"
MethodData method = null; //A temporary reference to a MethodData while it is being constructed.
FieldData field = null; //A temporary reference to a FieldData while it is being constructed.
//CALL getDeclaredMethods on declaredClass returns methods
//CALL setAccessible of AccessibleObject with methods and true
methods = declaredClass.getDeclaredMethods();
AccessibleObject.setAccessible(methods, true);
//FOR ndx = 1 to length of methods
// CONSTRUCT MethodData method from methods INDEX ndx
// CALL addMethodRow on view with method returns row
// CALL setMethodRowInterface on method with row
//ENDFOR
for (int ndx = 0; ndx < methods.length; ndx++)
{
method = new MethodData(methods[ndx], this);
method.setMethodRowInterface(view.addMethodRow(method));
this.methods.add(method);
}
//CALL getDeclaredFields on declaredClass returns fields
//CALL setAccessible of AccessibleObject with methods and true
fields = declaredClass.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
//FOR ndx = 1 to length of fields
//CONSTRUCT FieldData field from methods INDEX ndx
//CALL addFieldRow on view with field returns row
//ENDFOR
for (int ndx = 0; ndx < fields.length; ndx++)
{
field = new FieldData(fields[ndx], this);
view.addFieldRow(field);
this.fields.add(field);
}
//CALL getInterfaces on declaredClass returns interfaces
interfaces = declaredClass.getInterfaces();
//FOR ndx = 1 to length of interfaces
//CALL populateView with interfaces INDEX ndx
//ENDFOR
for (int ndx = 0; ndx < interfaces.length; ndx++)
{
populateView(interfaces[ndx]);
}
//CALL getSuperclass on declaredClass returns superClass
Class superClass = declaredClass.getSuperclass();
//IF superClass not null
//THEN
//CALL populateView with superClass
//ENDIF
if(superClass != null)
{
populateView(superClass);
}
}
/**
* Sets the view that will display the models information.
*
* @param viewAbs the view that will be used by the model to display
* its information.
*/
public void setView(ETAViewAbstract viewAbs)
{
//SET view to viewAbs
view = viewAbs;
//CONSTRUCT ObjectInspector insp with view
//SET inspect to insp
//inspect = new ObjectInspector(view);
}
/**
* Sets the mainTestObject to be obj, repopulates the view with the
* methods and fields declared in obj
*
* Pre-conditions: the view has been set
* Post-conditions: view is enable
* mainTestObject set to obj
* @param the Object that the user wants to test, sets mainTest to obj
*/
public void loadObject(Object obj)
{
//CALL addParameterData with obj and "Main Test Object"
//addParameterData(obj, "Main Test Object");
//CALL getClass on obj returns cls
//CALL setMainTestClass with cls
setMainTestClass(obj.getClass());
//SET mainTestObject to obj
Assert.preCondition(obj != null, "Can't load null object");
mainTestObject = obj;
//CALL enableMainTest on view with true
view.enableMainTest(true);
//CALL forName with "Component" returns compClass
//IF CALL isAssignableFrom on class of Component with mainTestClass
//CALL setPreviewComponent with obj
//ENDIF
if(Component.class.isAssignableFrom(mainTestClass))
{
view.setPreviewComponent((Component)obj);
}
}
/**
* Constructs the main test class from the Constructor object con with the
* with the parameters stored in datas.
*
* Pre-conditions: view is not null
* con is constructor for Main Test Class
* Post-conditions: mainTestObject is not null
* @param con the constructor that will be used to construct the Main
* Test Object
* @param datas The parameters that will be used to construct the Main
* Test Object
* @param name The name that will be used to describe and refer to the Main Test Object
*/
public void instantiateClass(Constructor con, ParameterDataInterface[] datas, String name)
{
Object[] tempData = null; // An array to store all the contents of datas as Objects
//CONSTRUCT parameters array of Object with length equal to data length
//FOR ndx = 1 to parameters length
//CALL getValueObject on datas INDEX ndx returns obj
//SET parameters INDEX ndx to obj
//ENDFOR
//TRY
//CALL newInstance on con with parameters return instance
//SET mainTestObject to instance
//CALL addParameterData with mainTestObject and name
//CALL forName with "Component" returns compClass
//IF CALL isAssignableFrom on compClass with mainTestClass
//CALL setPreviewComponent with mainTestObject
//ENDIF
//CALL enableThis on view with true
//ENDTRY
con.setAccessible(true);
tempData = new Object[datas.length];
for (int ndx = 0; ndx < datas.length; ndx++)
{
tempData[ndx] = ( ( ParameterData ) datas[ndx]).getValueObject();
}
try
{
mainTestObject = con.newInstance( tempData );
addParameterData( mainTestObject, name);
if(Component.class.isAssignableFrom(mainTestClass))
{
view.setPreviewComponent((Component)mainTestObject);
}
view.enableMainTest(true);
//CATCH InstantiationException
//CALL getDeclaringClass on con returns abstractClass
//CALL getName on abstractClass returns abstractName
//CONCAT "Can not create objects of abstract types. " with abstractName
//returns abstractError
//CONCAT abstractError with " is an abstract type" returns
//abstractFullMessage
//CALL println of err in ETA with abstractFullMessage
//CALL printStackTrace of InstantiationException with err in ETA
//ENDCATCH
} catch (InstantiationException ins)
{
ETA.err.println("Can not create objects of asbtract types. " + con.getDeclaringClass().getName() +
" is an abstract type.");
ins.printStackTrace(ETA.err);
//CATCH IllegalAccessException
//CONSTRUCT String msg with "The ETA was not allowed to access this
//constructor."
//CALL println of err in ETA with msg
//CALL printStackTrace of IllegalAccessException with err in ETA
//ENDCATCH
} catch(IllegalAccessException acc)
{
ETA.err.println("The ETA was not allowed to access this constructor.");
acc.printStackTrace(ETA.err);
//CATCH IllegalArgumentException
//CONSTRUCT String msg with "An error has caused a value of the wrong
//type to be passed to the constructor, please constact ETA support"
//CALL println of err in ETA with msg
//CALL printStackTrace of IllegalArgumentException with err in ETA
//ENDCATCH
} catch (IllegalArgumentException exe)
{
ETA.err.println("An error has caused a value of the wrong type to be passed " +
"to the constructor, please contact ETA support");
exe.printStackTrace(ETA.err);
//CATCH InvocationTargetException
//CALL printStackTrace of InvocationTargetException
//ENDCATCH
} catch (InvocationTargetException inv)
{
inv.printStackTrace();
}
//CONSTRUCT String msg "Main Test Class Constructor "
String msg = "Main Test Class Constructor ";
//CONSTRUCT String msg2 " called"
String msg2 = " called";
//CONSTRUCT String with "with "
String with = "with ";
//CALL println on log of ETAMainModel with msg name of con msg2
//FOR ndx = 1 to parameters length
//CALL println on log of ETAMainModel with toString of
//parameters INDEX ndx
//ENDFOR
}
/**
* Adds the specified ParameterDataListener to recieve events for the model
* when ParameterData is added removed or changed
*
* Pre-conditions: listeners is not null
* Post-conditions: none
*
* @param list a listener that wants to be informed when a ParameterData is
* is added changed or removed
*/
public void addParameterDataListener(ParameterDataListener list)
{
//CALL add on listeners with list
//listeners.add(list);
pool.addParameterListener(list);
}
/**
* Removes the specified ParameterDataListener from recieving events for the model
* when ParameterData is added removed or changed
*
* Pre-conditions: listeners is not null
* Post-conditions:
*
* @param list the listener that is no longer interested in listening to
* added removed and changed ParameterData
*/
public void removeParameterDataListener(ParameterDataListener list)
{
//CALL remove on listeners with list
//listeners.remove(list);
pool.removeParameterListener(list);
}
/**
* Used to determin if the specified ParameterDataListener is registered
* to recieve events from the model for added removed and changed
* ParameterData.
*
* Pre-conditions: listeners is not null
* Post-conditions:
*
* @param list the listener that is tested to see if it is listening to
* added removed changed ParameterData
* @return true if list is listening to added removed or changed
* false otherwise
*/
public boolean isParameterDataListener(ParameterDataListener list)
{
//CALL constains on listerers with list returns b
//RETURN b
return false;
}
/**
* Returns the Main Test Class that the user is testing
*
* @return the Main Test Class of this Model
*/
public Class getMainTestClass()
{
//RETURN mainTestClass
return mainTestClass;
}
/**
* Constructs and added a new ParameterData for the newItem Object and the
* name and adds it to the pool
*
* Pre-conditions: pool is not null
* Post-conditions:
*
* @param newItem the value of the item that is being added to the pool
* @param name a String describing the source of the value, what method
* it was returned from or what field it represents.
*/
public void addParameterData(Constructor con, ParameterDataInterface[] params, String name)
{
Object[] conParams = null; //To contain all the contents of params with object references
// CONSTUCT Object[] conParams from params
// CALL setAccessible on con with true
// CALL newInstance on con with conParams returns data
// CALL addParameterData on this with data and name
conParams = new Object[params.length];
for (int ndx = 0; ndx < params.length; ndx++)
{
conParams[ndx] = ((ParameterData) params[ndx]).getValueObject();
}
con.setAccessible(true);
try
{
addParameterData(con.newInstance(conParams), name);
// CATCH InstantiationException
// CALL getDeclaringClass on con returns abstractClass
// CALL getName on abstractClass returns abstractName
// CONCAT "Can not create objects of abstract types. " with abstractName
// returns abstractError
// CONCAT abstractError with " is an abstract type" returns
// abstractFullMessage
// CALL println of err in ETA with abstractFullMessage
// CALL printStackTrace of InstantiationException with err in ETA
// ENDCATCH
} catch(InstantiationException exc)
{
ETA.err.println("Can not create object of abstact types. ");
ETA.err.println(con.getDeclaringClass().getName() + " is an abstract type.");
exc.printStackTrace(ETA.err);
// CATCH IllegalAccessException
// CONSTRUCT String msg with "The ETA was not allowed to access this
// constructor."
// CALL println of err in ETA with msg
// CALL printStackTrace of IllegalAccessException with err in ETA
// ENDCATCH
} catch(IllegalAccessException exc)
{
ETA.err.println("The ETA was not allowed to access this constructor.");
exc.printStackTrace(ETA.err);
// CATCH IllegalArgumentException
// CONSTRUCT String msg with "An error has caused a value of the wrong
// type to be passed to the constructor, please constact ETA support"
// CALL println of err in ETA with msg
// CALL printStackTrace of IllegalArgumentException with err in ETA
// ENDCATCH
} catch(IllegalArgumentException exc)
{
ETA.err.println("The constuctor was passed an invalid parameter, " +
"constuction failed");
exc.printStackTrace(ETA.err);
// CATCH InvocationTargetException
// CALL printStackTrace of InvocationTargetException
// ENDCATCH
} catch(InvocationTargetException exc)
{
exc.printStackTrace(ETA.err);
}
}
/**
* Constructs and added a new ParameterData for the newItem Object and the
* name and adds it to the pool
*
* Pre-conditions: pool is not null
* Post-conditions:
*
* @param newItem the value of the item that is being added to the pool
* @param name a String describing the source of the value, what method
* it was returned from or what field it represents.
*/
public void addParameterData(Object newItem, String name)
{
//CONSTRUCT ParameterData param from newItem and name
//CALL addParameterData on pool with param
pool.addParameterData(new ParameterData(newItem, name, this));
}
/**
* Constructs and addds a new ReturnedData from the newItem Object and the
* name and adds it to the pool
*
* Pre-conditions: pool is not null
* Post-conditions:
*
* @param newItem is the value of the item that is being added to the pool
* @param name is a String describing the source of the value, what method
* it was returned from or what field it represents.
*/
public void addReturnedData(Object value, String from)
{
//CONSTRUCT ReturnedData data from value and from
//CALL addReturnedData on pool with data
pool.addReturnedData(new ReturnedData(value, from, this));
}
/**
*Returns the reference to the Main Test Object
*
*@return the reference to the Main Test Object
* Pre-conditions:
* Pre-conditions: the view has been set
* Post-conditions:
*/
public void parameterDataAdded(ParameterDataInterface added)
{
//CALL addParameterRow on view with added
if (view != null)
view.addParameterRow(added);
}
/**
* Changes the view to reflect the removed ParameterData in the pool
*
* Pre-conditions: the view has been set
* Post-conditions:
*/
public void parameterDataRemoved(ParameterDataInterface removed)
{
//CALL removeParameterRow on view with removed
view.removeParameterRow(removed);
}
}
/**
*Listens to the ObjectPool for added ReturnedData and removed ReturnedData
* Pre-conditions: the view has been set
* Post-conditions: none
*/
public void returnedAdded(ReturnedData added)
{
//CALL addReturnedRow on view with added
if (view != null)
view.addReturnedRow(added);
}
/**
* Changes the view to reflect the removed ReturnedData in the pool
*
* Pre-conditions: the view has been set
* Post-conditions: none
*/
public void returnedRemoved(ReturnedData removed)
{
//CALL removeReturnedRow on view with removed
view.removeReturnedRow(removed);
}
}
}
* Post-conditions:
*@param classToMake the class object that the caller wants a class for.
*@return a Class object that is named by the param string.
*/
public static Class nameToClass(String nameOfClass)
{
//IF CALL endsWith on nameOfClass with "[]"
//CALL length on nameOfClass returns lengthOfClassToMake
//CALL substring on nameOfClass with 0 and lengthOfClassToMake -2 returns componentClassName
//CALL nameToClass of ETAMainModel with nextClass returns componentClass
//CALL newInstance of Array with componentClass and 0 returns arrayObject
//CALL getClass on arrayObject returns classMade
//RETURN classMade
//ENDIF
if(nameOfClass.endsWith("[]"))
{
return Array.newInstance(ETAMainModel.nameToClass(nameOfClass.
substring(0, nameOfClass.length() -2)), 0).getClass();
//ELSE
//TRY
//CALL forName of Class with nameOfClass returns classMade
//RETURN classMade
//ENDTRY
//CATCH ClassNotFoundException
//CALL println of System.out with "If the class is not found, we are in trouble"
//ENDCATCH
//ENDELSE
} else
{
try
{
return Class.forName(nameOfClass);
} catch(ClassNotFoundException exc)
{
System.err.println("An error has occured in ETA, please reboot");
}
}
throw new RuntimeException("Statement should not be reached");
}
/**
*This method will be used to convert array names and primitive names
*of classes to a name that is more appropreiate. Such as changing [B
*for a byte array to java.lang.Byte[]
* Pre-conditions:
* Post-conditions:
*@param nameToMake the class object that the caller wants a name for.
*@return a formated name representing the name of nameToMake.
*/
public static String classToName(Class nameToMake)
{
// CALL isArray on nameToMake returns classIsArray
// IF classIsArray
// CONSTUCT String brackets as "[]"
// CALL getComponentType on nameToMake returns arrayType
// CALL nameToMake of ETAMainModel on arrayType returns arrayTypeName
// RETURN arrayTypeName + brackets
Assert.assert(nameToMake != null, "nameToMake cannot be null!");
if (nameToMake.isArray())
{
Assert.assert(nameToMake.isArray(), "nameToMake.isArray() must be true!");
return ETAMainModel.classToName(nameToMake.getComponentType()) + "[]";
// ELSE
// CALL isPrimitive on nameTomake returns classIsPrimitive
// IF classIsPrimitive
// IF CALL equals on nameToMake with Boolean.TYPE
// RETURN java.lang.Boolean
// ELSEIF CALL equals on nameToMake with Byte.TYPE
// RETURN java.lang.Byte
// ELSEIF CALL equals on nameToMake with Character.TYPE
// RETURN java.lang.Character
// ELSEIF CALL equals on nameToMake with Double.TYPE
// RETURN java.lang.Double
// ELSEIF CALL equals on nameToMake with Float.TYPE
// RETURN java.lang.Float
// ELSEIF CALL equals on nameToMake with Integer.TYPE
// RETURN java.lang.Integer
// ELSEIF CALL equals on nameToMake with Long.TYPE
// RETURN java.lang.Long
// ELSEIF CALL equals on nameToMake with Short.TYPE
// RETURN java.lang.Short
// ELSE
// RETURN void
// ENDIF
} else if (nameToMake.isPrimitive())
{
Assert.assert(nameToMake.isPrimitive(), "nameToMake must be primitive here!");
if (nameToMake.equals(Boolean.TYPE))
{
Assert.assert(nameToMake.equals(Boolean.TYPE), "nameToMake must be boolean here!");
return "java.lang.Boolean";
}
else if (nameToMake.equals(Byte.TYPE))
{
Assert.assert(nameToMake.equals(Byte.TYPE), "nameToMake must be of type Byte here!");
return "java.lang.Byte";
}
else if (nameToMake.equals(Character.TYPE))
{
Assert.assert(nameToMake.equals(Character.TYPE), "nameToMake must be Character here!");
return "java.lang.Character";
}
else if (nameToMake.equals(Double.TYPE))
{
Assert.assert(nameToMake.equals(Double.TYPE), "nameToMake must be Double here!");
return "java.lang.Double";
}
else if (nameToMake.equals(Float.TYPE))
{
Assert.assert(nameToMake.equals(Float.TYPE), "nameToMake must be Float here!");
return "java.lang.Float";
}
else if (nameToMake.equals(Integer.TYPE))
{
Assert.assert(nameToMake.equals(Integer.TYPE), "nameToMake must be integer here!");
return "java.lang.Integer";
}
else if (nameToMake.equals(Long.TYPE))
{
Assert.assert(nameToMake.equals(Long.TYPE), "nameToMake must be long here!");
return "java.lang.Long";
}
else if (nameToMake.equals(Short.TYPE))
{
Assert.assert(nameToMake.equals(Short.TYPE), "nameToMake must be short here!");
return "java.lang.Short";
}
else
{
return "void";
}
// ELSE
// CALL getName on nameToMake returns name
// RETURN name
// ENDIF
} else
{
Assert.assert(!nameToMake.isPrimitive(), "nameToMake cannot be primitive here!");
Assert.assert(!nameToMake.isArray(), "nameToMake cannot be an array here!");
return nameToMake.getName();
}
}
/**
* Returns the current value of descNum and increments descNum by one, this
* will be used to create names for primitive ParameterDatas that were created
* from a ParameterObjectComboBox
*
* Post-conditions:
*
* @return the current value of descNum to be concatenated on to the name of a
* user created primitive from ParameterObjectComboBox
*/
public static int getNumber()
{
//COPY descNum to num
//INCREMENT descNum
//RETURN num
return 0;
}
/**
*Will store all the references to ParameterData and ReturnedData Objects,
*and will also inform the ETAMainModel when a ParameterData or ReturnedData
*has been added or removed
*/
protected static ObjectPool pool = new ObjectPool();
/**
*A count that will be used to defferentiate one user created primitive from
*ParameterObjectComboBox from another
*/
protected static int descNum = 1;
/**
*The reference to the object that the user has created to test with the ETA,
*commonly referred to as the "THIS"
*edit and change the Object
*/
protected ObjectInspector inspect;
/**
*@link aggregation
* @associates <{FieldData}>
*
*A Collection of all the FieldData associated to the MainTestClass
*/
protected Collection fields;
/**
*@link aggregation
* @associates <{MethodData}>
*
*A Collection of all the MethodData associated to the MainTestClass
*/
protected Collection methods;
/**
*Listens to the ObjectPool for added ParameterData and removed ParameterData