Collection element type detection
EclipseUML 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 Company
{
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.
|
Using
local variable
|
public void addEmployee(Employee employee)
{
Collection localVariable = employees;
localVariable.add(employee);
}
|
|
Clall
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:
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 , 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 int getEmployeeIndex(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.
EclipseUML Enterprise edition implements this sophistic mechanism. It is used
only when the first category calls are missing.
|