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