package Sequenic.T2 ;
import java.util.* ;
/**
* Represents object pools. An instance of this class is called an
* object pool, or simply pool. It is used by T2's test engine to keep
* track of objects created and accessed during its executions --see
* the explanation of the {@link Sequenic.T2 Sequenic.T2 package}.
*
*
A Pool will be organized as follows. Essentially, it is a set
* of objects. Let's call this set S. The pool contains an object
* map, which is a mapping from unique integer keys to objects in
* S. The pool also has a domain map, which is a mapping from
* Class to 'domains'. If the domain map maps a Class C to a domain D,
* then D is essentially a set of objects, all should be of class
* C. Each domain will be implemented as a linked list of the integer
* indices over the object map.
*
* @see Sequenic.T2.RndEngine#RndTest
*/
public class XPool {
private HashMap objectMap ;
private HashMap> domainMap ;
private int objectCount ;
/**
* Just a random generator.
*/
//private Random rnd ;
/**
* Create an empty pool.
*/
public XPool() {
objectMap = new HashMap() ;
domainMap = new HashMap>() ;
objectCount = 0 ;
//rnd = new Random() ;
}
/**
* Returns the number of objects in the pool.
*/
public int get_objectCount() { return objectCount ; }
/**
* This will reset the pool to whatever its normal starting
* state. This method is called whenever a new execution is
* started. The default behavior of this method is to empty the
* pool. To create a pool that is pre-populated, make a subclass
* and overide this method so that reset will fill the pool with
* its pre-population.
*/
public void reset() {
// originally HashMap, changed to LinkedHashMap to make iteration order
// deterministic, to avoid tripping oracle generator
objectMap = new LinkedHashMap() ;
domainMap = new LinkedHashMap>() ;
objectCount = 0 ;
}
/**
* Returns the object from objectMap indexed with i.
*
* Precond: i should be an existing index.
*/
public Object get(int i) { return objectMap.get(i) ; }
/**
* Randomly draw an object of class C from the pool. It actually
* returns the index of the object rather than the object
* itself. It returns null if no instance of C is found in the
* pool.
*
* WP: for the benchmark, this is changed to always return the first
* index, to make it deterministic.
*/
// public Integer rndGetIndex(Class C) { ... }
public Integer getIndex(Class C) {
// get all classes from the pool which are either C or
// subclasses of C:
LinkedList classes = new LinkedList() ;
for (Class D : domainMap.keySet())
if (C.isAssignableFrom(D)) classes.add(D) ;
if (classes.isEmpty()) return null ;
// Now pick one domain randomly:
//Class chosenClass = classes.get(rnd.nextInt(classes.size())) ;
Class chosenClass = classes.getFirst() ;
// now randomly pick an index from the corresponding domain:
LinkedList domain = domainMap.get(chosenClass) ;
// this branch is actually not feasible:
// if (domain.isEmpty()) return null ;
// else return domain.get(rnd.nextInt(domain.size())) ;
// else
int k = domain.getFirst() ;
//System.err.print("### getIndex(" + C + ") -->" + k) ;
return k ;
}
/**
* Add an object u into the pool. It returns the index
* of u in the pool's object map.
*/
public int put(Object u) {
//if (u==this) throw new IllegalArgumentException() ;
int index = objectCount ;
Class C = u.getClass() ;
objectCount++ ;
objectMap.put(index,u) ;
if (domainMap.containsKey(C))
(domainMap.get(C)) . add(index) ;
else {
LinkedList domain = new LinkedList() ;
domain.add(index) ;
domainMap.put(C,domain) ;
}
return index ;
}
}