org.jwalk.core
Class ObjectGenerator

java.lang.Object
  extended by org.jwalk.core.ValueGenerator
      extended by org.jwalk.core.ArrayGenerator
          extended by org.jwalk.core.ObjectGenerator
All Implemented Interfaces:
MasterGenerator, Generator

public class ObjectGenerator
extends ArrayGenerator

ObjectGenerator is the standard generator of object, array and basic values. Since Generators can be quite complicated, the standard ObjectGenerator is split into three parts, with ValueGenerator being the root of a hierarchy, whose descendants are ArrayGenerator and finally ObjectGenerator. ObjectGenerator is able to synthesise values of most Java types, including value-types, array-types and object-types. ObjectGenerator is the first concrete generator to completely satisfy the interface of MasterGenerator. It is the default generator used by every JWalker.

Locally, ObjectGenerator is able to synthesise values of any class which has public constructors and is not abstract. It inherits the ability to synthesise array values from ArrayGenerator; and simple values from ValueGenerator. Other custom generators may be added to an ObjectGenerator when it is created. A standard set of custom generators is loaded by the JWalker's Settings (and are configurable by the tester). These provide the following capabilities:

Through its delegate StringGenerator, ObjectGenerator also provides the ability to synthesise 26 conventional strings in alphabetical order. Through its delegate InterfaceGenerator, ObjectGenerator also provides the ability to synthesise concrete values for certain interfaces (in an ad-hoc manner). Through its delegate EnumGenerator, ObjectGenerator also provides the ability to synthesise values of enumerated types. Through its delegate PlatformGenerator, ObjectGenerator also provides the ability to synthesise values of the Date, Locale and Charset types.

Version:
1.0
Author:
Anthony Simons

Field Summary
protected  java.util.Map<java.lang.Class<?>,java.lang.Integer> indexMap
          The bag counting the created instances of each class
protected  java.util.Map<java.lang.Object,java.lang.String> oracleMap
          The log mapping from object addresses to oracle values
protected  java.lang.Object target
          The target object, the instance of the test class, which we may need to return as a value in response to a request for a binary method argument.
protected  java.lang.Class<?> targetType
          The target type we need to retain, in case of needing to synthesise values for binary methods.
protected  JWalker walker
          The JWalker which created this Generator.
 
Fields inherited from class org.jwalk.core.ValueGenerator
delegates
 
Constructor Summary
ObjectGenerator(JWalker walker)
          Creates an ObjectGenerator.
 
Method Summary
 boolean canCreate(java.lang.Class<?> type)
          Reports whether this ObjectGenerator synthesises objects of a given type.
protected  java.lang.Object createClass(java.lang.Class<?> type)
          Returns an instance of any metaclass type "Class>T<".
protected  java.lang.Object createFromNextConstructor(java.lang.Class<?> type)
          Tries all the constructors of a type until one of them succeeds.
protected  java.lang.Object createObject(java.lang.Class<?> type)
          Creates the next instance of a general object-type.
 JWalker getJWalker()
          Returns the JWalker which created this ObjectGenerator.
 java.lang.Object getTarget()
          Returns the target object, if this has already been logged.
 java.lang.Class<?> getTargetType()
          Returns the type of the target object.
protected  boolean isMetaClass(java.lang.Class<?> type)
          Reports if a type is any metaclass type "Class>T<".
 void logObject(java.lang.Object object)
          Registers a synthesised object with this ObjectGenerator.
 void logTarget(java.lang.Object object)
          Registers the target object with this ObjectGenerator.
 java.lang.Object nextValue(java.lang.Class<?> type)
          Creates the next quasi-unique value in sequence for a particular type.
 java.lang.String oracleValue(java.lang.Object object)
          Converts an object into its oracle value format.
 
Methods inherited from class org.jwalk.core.ArrayGenerator
createArray, isArray, isPrintable
 
Methods inherited from class org.jwalk.core.ValueGenerator
addDelegate, createPrimitive, createWrapped, isEnumerated, isPrimitive, isWrapped
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

walker

protected JWalker walker
The JWalker which created this Generator. MasterGenerators keep a back reference to their JWalker, so that they may access the Settings and Channels, in case they need to alter any setting, or communicate with the tester.


targetType

protected java.lang.Class<?> targetType
The target type we need to retain, in case of needing to synthesise values for binary methods. This is supplied upon construction and is the same as the test class.


target

protected java.lang.Object target
The target object, the instance of the test class, which we may need to return as a value in response to a request for a binary method argument.


oracleMap

protected java.util.Map<java.lang.Object,java.lang.String> oracleMap
The log mapping from object addresses to oracle values


indexMap

protected java.util.Map<java.lang.Class<?>,java.lang.Integer> indexMap
The bag counting the created instances of each class

Constructor Detail

ObjectGenerator

public ObjectGenerator(JWalker walker)
Creates an ObjectGenerator. Installs the standard delegate Generators: StringGenerator, EnumGenerator, InterfaceGenerator and PlatformGenerator. Initialises all the seed values for primitive types and indices.

Method Detail

canCreate

public boolean canCreate(java.lang.Class<?> type)
Reports whether this ObjectGenerator synthesises objects of a given type. This method fulfils the contract specified in Generator for boolean canCreate(Class). In principle, ObjectGenerator can synthesise every type. However, this is only an approximation, since third-party software may contain unknown interfaces and abstract classes, for which custom generators must be supplied.

Parameters:
type - the requested type.
Returns:
true, even though this ObjectGenerator may sometimes fail.

isMetaClass

protected boolean isMetaClass(java.lang.Class<?> type)
Reports if a type is any metaclass type "Class>T<".

Parameters:
type - the type to inspect.
Returns:
true if the type is identical to Class.class.

createClass

protected java.lang.Object createClass(java.lang.Class<?> type)
Returns an instance of any metaclass type "Class>T<". Typically, a request to instantiate a metaclass will most likely work if we give back the same class as the test class. This is only a heuristic.

Parameters:
type - the requested metaclass type.
Returns:
the same class as the test class.

createFromNextConstructor

protected java.lang.Object createFromNextConstructor(java.lang.Class<?> type)
                                              throws GeneratorException
Tries all the constructors of a type until one of them succeeds. Extracts all of the constructors of the type, then tries to invoke them one at a time, until one succeeds, or all have failed. For each Constructor, extracts its parameter types and creates corresponding parameter values, calling nextValue(type) recursively.

Parameters:
type - the requested type.
Returns:
a generated object of this type.
Throws:
GeneratorException, - if none of the constructors for the type eventually succeed; or if a SecurityManager refuses to grant access to the type's constructors.
GeneratorException

createObject

protected java.lang.Object createObject(java.lang.Class<?> type)
                                 throws GeneratorException
Creates the next instance of a general object-type. Tries the default constructor first, but if not available, picks another constructor and recursively synthesises values for the construction arguments. May fail if no public constructors are available.

Parameters:
type - the requested type.
Returns:
a generated object of this type.
Throws:
GeneratorException, - if no object of this type could be synthesised.
GeneratorException

nextValue

public java.lang.Object nextValue(java.lang.Class<?> type)
                           throws GeneratorException
Creates the next quasi-unique value in sequence for a particular type. This method fulfils the contract specified in Generator for Object nextValue(Class). If the requested type is the same as the type of the target, the first value returned will be the target object (assuming this exists) and subsequent instances will be different objects. In general, this ObjectGenerator checks first whether the requested type is handled by one of the CustomGenerators that were added as delegates, using this in preference to local algorithms. Otherwise, analyses the requested type and synthesises an instance of the type using one of the algorithms: createPrimitive(type), createWrapped(type), createArray(type), or createObject(type). Standard delegate CustomGenerators include: StringGenerator, EnumGenerator, InterfaceGenerator and PlatformGenerator.

Parameters:
type - the requested type.
Returns:
a synthesised object of this type.
Throws:
GeneratorException, - if no object of this type could be synthesised; or if one of the custom generators failed.
GeneratorException - if no value of this type could be synthesised.

logTarget

public void logTarget(java.lang.Object object)
Registers the target object with this ObjectGenerator. The importance of this is that certain binary methods may need another object like this one, or a class like the target's class.

Parameters:
object - the target object.

getTarget

public java.lang.Object getTarget()
Returns the target object, if this has already been logged.

Returns:
the target object, the instance of the test class.

getTargetType

public java.lang.Class<?> getTargetType()
Returns the type of the target object. This can always be returned, even if the target has not yet been created.


getJWalker

public JWalker getJWalker()
Returns the JWalker which created this ObjectGenerator. This method allows CustomGenerator classes to access the JWalker, the Settings and the Channels APIs from their owning MasterGenerator.


logObject

public void logObject(java.lang.Object object)
Registers a synthesised object with this ObjectGenerator. Every synthesised test input, or returned test result, must be logged by this ObjectGenerator, for later recognition. If the logged object has no unique printable, persistent representation, an oracle value is created for it, and is stored against the object in a map. Otherwise, no action is taken. Every synthesised object must be tested; and any object is only logged at most once in the map.

Parameters:
object - the object to be logged.

oracleValue

public java.lang.String oracleValue(java.lang.Object object)
Converts an object into its oracle value format. If the object has an encoded oracle value format, based on the object's class name and an index, representing the rank order (in its class) in which the object was created by this ObjectGenerator, returns this oracle value. Otherwise, invokes the super-method to obtain the conventional persistent, printed representation for an array or a value.

Specified by:
oracleValue in interface MasterGenerator
Overrides:
oracleValue in class ArrayGenerator
Parameters:
object - an object synthesised by this ObjectGenerator.
Returns:
the encoded oracle value format.