The steps performed in analyzing a class
We saw from the index page that for each
Java source, Jemos Clanker first delegates to the Java parser the
job of externalizing a Java source class into one or more
Tree objects. Still in the same page we saw that the order
in which the Tree objects are then available is:
- Package definitions
- Import declarations
- Javadoc comments
- Class members (class, method, instance variable
definitions)
In this section we'll see how a Tree representing a Java source class
is processed by Jemos Clanker in order to extract the required information
in a JavaBean-like structure (literally an instance of
uk.co.jemos.clanker.component.Clazz).
Below you'll find a sequence diagram which illustrates what the
uk.co.jemos.clanker.lyrinx.ClassLyrinx class does:
This are the steps performed by the uk.co.jemos.clanker.lyrinx.ClassLyrinx
class:
- To maintain the possibility of 'programming by interfaces'
I had to design all Lyrinx so that these accept a generic
com.sun.tools.javac.Tree object as parameter. If
one wants to be able to access all the instance methods offered
by specific Tree objects (such as the one representing a
class), this object needs to be narrowed to the appropriate
sub-type. So the first thing the ClassLyrinx.process() method
does is to narrow down the com.sun.tools.javac.Tree.[some-object] to
an instance of com.sun.tools.javac.Tree.ClassDef.
- It then asks the uk.co.jemos.clanker.components.ComponentManufactory
to create the bean-like class which represents the object that
Jemos Clanker offers to the external world as a representation of
a Java source class: an instance of
uk.co.jemos.clanker.components.Clazz.
- The method then sets the class name as instance variable in the
Clazz object. This name is just the class name, not the fully qualified
name, for which another instance variable is separately set (see below).
- The method then retrieves from the Amplimet the Jemos Clanker object parent of this class
thus an instance of uk.co.jemos.clanker.components.Package,
compose the fully qualified name of the class by appending to the
package name the class name and sets this name as instance variable
in the Clazz object.
- If you went through the
paragraph
which explained where a class gets processed, you probably remember
that the ThapterImpl.fillTheAmplimet() method, before actually
starting the process of the Class part of the Tree object, deals with
imports and Javadoc and that, for each class, fills the imports and
Javadoc instance variables in the ThapterImpl class so that processors
(Lyrinx) down the line will be able to access those information. This
is exactly what happens here. Before the ClassLyrinx.process()
method is invoked, imports and Javadocs have already been processed
and made available in the ThapterImpl class as instance variables.
This method then retrieves the Javadocs from the ThapterImpl class,
selects only those relevant to this class (to exclude the ones related
to inner classes) and sets those comments as instance variables in the
Clazz object. As you can see, every action in this like in all
other Lyrinx is to set the state of a
uk.co.jemos.clanker.components.Clazz object so as to make it
available for clients.
- The method then loops through all the interfaces implemented by this
class and sets these in a collection of String objects containing
the fully qualified name of those interfaces.
- The method then loops through the Tree.[some-object] objects, children
of a class (like methods and instance variables, but also inner classes)
and for each one of them invokes the appropriate Lyrinx, which creates
an instance of uk.co.jemos.clanker.components.Component and sets
it as children of the Clazz component.
- The method then sets the class modifiers in a collection
of String objects. Modifiers are strings like 'public',
'static', etc.
- The method then asks the uk.co.jemos.clanker.lyrinx.LyrinxManufactory
a processor for Annotations and invokes its process() method passing
as parameter the Tree.Annotation object as parameter. It then
adds each annotation returned by the processor to the Clazz object.
A uk.co.jemos.clanker.components.Clazz object has to offer the following
attributes:
- Annotations, represented by a collection of
uk.co.jemos.clanker.components.Annotation objects.
- Javadocs, represented by an instance of the
uk.co.jemos.clanker.components.ClassComment class.
- The class fully qualified name (package name + class name)
- The list of implemented interfaces, represented by a
collection of Strings
- The inner classes, represented by a collection of
uk.co.jemos.clanker.components.Clazz objects
- The list of methods, represented by a collection of
uk.co.jemos.clanker.components.Method classes
- The list of modifiers, contained in a collection of Strings
- The class name
- The unique id of the parent class, containing the hashcode of
the uk.co.jemos.clanker.components.Package parent of this class
- The instance and class variables, contained in a collection of
uk.co.jemos.clanker.components.Variable class