Collection element type detection

eUML2 Reverse engineering engine captures the element type in a collection by analysing content accessing code. For example, the argument of collection method add() may indicate the element type:

public class Category
{
	private List employees = new ArrayList();
	public Company(List employees) {
		this.employees = employees;
	}

	public void addEmployee(Employee employee) {
		employees.add(employee);
	}

	public Collection getEmployees() {
		return employees;
	}
}

The idea is very simple. But the real use cases are mush more complex. The same method may have different implementations.

Desciption

Codes

Using local variable

public	void addEmployee(Employee employee)
{
   Collection localVariable = employees;
   localVariable.add(employee);
}

Call getter

public	void addEmployee(Employee employee)
{
   getEmployees().add(employee);
}

Using getter and local variable

public	void addEmployee(Employee employee)
{
   Collection localVariable = getEmployees();
   LocalVariable.add(employee);
}

Of course, these codes can be used outside of the class Company.

According the accessing type of this attribute, we distinguee the analyze mechanism in two categories:

  1. Getter category
  2. Setter category

The first one allows the forward analyze, the analyzer can follow the execution order. The typical example is the iteration method (see below). It is much easy than Setter category, which needs backward analyze mechanism.

1. Getter category

Each accessing method may have a specific way to capture the element type. So we classify all relevant methods as following groups according to the model capture mechanism:

1.1 Add, Remove, Index and Test group

This group includes following methods:

Class

Method

java.util.Collection

boolean add(Object object)

java.util.Vector

void addElement(Object object)

java.util.Vector

void add(int index, Object object)

java.util.Vector

Object set(int index, Object object)

java.util.Vector

Object elementSet (Object object, int index)

java.util.Vector

void setElementAt (Object object, int index)

java.util.Vector

void insertElementAt (Object object, int index)

Class

Method

java.util.Collection

boolean remove(Object object)

java.util.Vector

boolean removeElement(Object object)

java.util.Vector

void removeElement (Object object)

 

Class

Method

java.util.List

int indexOf (Object object)

java.util.List

int lastIndexOf(Object object)

java.util.Vector

int lastIndexOf (Object object, int index)

java.util.Collection

boolean contains (Object object)

The capture mechanism of this group is simplest one comparing others. We just need identify the method call and capture argument type. For example:

public void removeEmployee(Employee employee)
{
	Collection localVariable = employees;
	localVariable.remove(employee);
}

or

public void removeEmployee(Employee employee)
{
	return employees.indexOf(employee);
}

1.2 Get group

This group consists of following methods:

Class

Method

java.util.List

Object get(int index)

java.util.Vector

Object elementAt(int index)

java.util.Vector

Object firstElement()

java.util.Vector

Object lastElement()

This group is a little bit difficult than previous one since we need analyse the next statements to capture the element type in type casting or the operator instanceof. For example,

public Employee getEmployeeAt(int index)
{
	return (Employee) employees.get(index);
}

or

public boolean hasEmployeeAt(int index)
{
	Object element = employees.get(index);
	return (element instanceof Employee);
}

1.3 Iteration group

This group consists of following methods

Class

Method

java.util.Collection

Iterator iterator ()

java.util.List

Iterator listIterator ()

java.util.List

Iterator listIterator (int index)

java.util.Vector

Enumeration elements ()

This group is more difficult than previous one again since it is necessary to analyse the following cast and instanceof statements only after element retrieve call such as next() or nextElement(). For example,

Iterator iterator = company.getEmployees().iterator();
while (iterator hasNext())
{
	Employee employee = (Employee) iterator.next();
}

or

for (Iterator iterator = company.getEmployees().iterator(); iterator hasNext();)
{
	Employee employee = (Employee) iterator.next();
}

All casting and operator instanceof must be ignored without calling next(). Otherwise, the result will be wrong:

Iterator iterator = company.getEmployees().iterator();
Address address = (Address) getAddress();
while (iterator.hasNext())
{
	Employee employee = (Employee) iterator.next();
}

2. Setter category

When the code assigns a filled container to this attribute, for example,

List employees = new ArrayList();
employees.add(new Employee());
Company company = new Company (employees);

or

List employees = new ArrayList();
employees.add(new Employee());
company.setEmployees(employees);

it is necessary to perform the semantic analyze following inverse execution order. eUML2 Studio edition implements this sophistic mechanism. It is used only when the first category calls are missing.