Extension of the Fractal ADL framework

This document describes how to extend the Fractal component model Architecture Description Language framework to define new parsers and modules.

Construction of abstract syntax trees

The Fractal ADL framework can be extended by implementing your own parser implementation or extending an existing implementation. A parser is an object that implements the Parser interface. A parser is in charge of producing abstract syntax trees, i.e. graphs of objects implementing the Node interface, from byte streams (see the parse(InputStream, String) method).

The node objects in ADL abstract syntax trees are strongly typed: they should implement strongly typed interfaces in addition to the Node interface. For instance, interfaces that have been defined in provided ADL modules are ComponentDefinition and Binding.

Two kinds of methods can be defined in those strongly typed interfaces:

  • getter and setter methods to access attributes of nodes, as following the JavaBeans conventions. The attributes must be of type String. For instance, Binding interface defines getter and setter methods for two attributes (from and to):
    public interface Binding {
        String getFrom();
        String getTo();
        void setFrom(String arg);
        void setTo(String arg);
    }
    
  • sub-nodes access methods for accessing typed collections of subnodes objects. In the Fractal ADL packages, the provided interfaces that define such methods are named with "Container" as a suffix, but this is not mandatory. If the subnodes to access are of arity 0..1 (at most one!), a getter and setter method pair must be defined. For instance, the ImplementationContainer defines nodes that can contain each one subnode object that implements the Implementation interface:
    public interface ImplementationContainer {
        Implementation getImplementation();
        void setImplementation(Implementation implementation);
    }
    
    If the subnodes to access are of arity 0..*, three methods must be defined instead, to add, remove and get the subnodes. For instance, the BindingContainer defines methods for accessing subnode objects that implement the Binding interface:
    public interface BindingContainer {
        void addBinding(Binding arg);
        Binding[] getBindings();
        void removeBinding(Binding arg);
    }
    

That way, node objects provide efficient strongly typed access to nodes attributes and sub-nodes through such typed interfaces, while still allowing to access those data from the Node meta-level interface.

Since it may be difficult to implement by hand in a parser every kinds of node classes with all interesting combinations of typed interfaces, an automatic generator is already provided in the ADL framework, as the NodeClassLoader class. It is based on the ObjectWeb ASM transformation system to implement dynamic Java class bytecode generation. It allows to dynamically generate and load classes of node objects according to the list of the attributes-access and subnodes-access interfaces to be implemented. The generator automatically generates classes that implements those interfaces, and the generated code stores the attributes and subnodes as fields of objects, and implements the Node interface for meta-level access.

The generator class must be subclassed to fit the generation strategy (dynamically or statically, etc.), and to actually implement a class loader. Following is an example class loader that allows to generate and load a foo.Bar node class that extends the standard AbstractNode class, and that implements the ComponentDefinition and BindingContainer interfaces:

import org.objectweb.fractal.adl.NodeClassLoader;
import org.objectweb.fractal.adl.AbstractNode;
import org.objectweb.fractal.adl.bindings.BindingContainer;
import org.objectweb.fractal.adl.components.ComponentDefinition;
import org.objectweb.asm.Type;
import org.objectweb.asm.ClassWriter;

public class MyClassLoader extends NodeClassLoader {

    public MyClassLoader(final ClassLoader parent) {
        super(parent);
    }


    public Class defineMyClass() throws ClassNotFoundException {

        ClassWriter classWriter = generateClass("foo/Bar",
            "Test node", Type.getInternalName(AbstractNode.class),
            new String[] {
                Type.getInternalName(ComponentDefinition.class),
                Type.getInternalName(BindingContainer.class)
            });

        byte[] b = classWriter.toByteArray();

        return defineClass("foo.Bar", b);

    }


    public static void main(String[] argv) throws Exception {

        MyClassLoader classLoader =
            new MyClassLoader(ClassLoader.getSystemClassLoader());

        Class nodeClass = classLoader.defineMyClass();

        Object node = nodeClass.newInstance();

        System.out.println("-----");
        System.out.println(nodeClass.getName());
        System.out.println(nodeClass.getSuperclass().getName());

        System.out.println("-----");
        Class[] interfaces = nodeClass.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
            System.out.println(interfaces[i].getName());
        }

        System.out.println("-----");
        AbstractNode anode = (AbstractNode) node;
        System.out.println(anode.astGetType());

        System.out.println("-----");
        ComponentDefinition nodeCD = (ComponentDefinition) node;
        nodeCD.setExtends("blahblah");
        System.out.println(nodeCD.getExtends());

    }

}

The execution of the main method generates the following output:

-----
foo.Bar
org.objectweb.fractal.adl.AbstractNode
-----
org.objectweb.fractal.adl.components.ComponentDefinition
org.objectweb.fractal.adl.bindings.BindingContainer
-----
Test node
-----
blahblah

New parser implementation

TODO

Extending the XML parser implementation

TODO


History of this document

  • 2005-11-08: changed the license of this document to the GNU Free Documentation License
  • 2005-08-09: modified
  • 2005-06-07: first version of this document

Copyright

Copyright © 2005 Romain Lenglet.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free S oftware Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is available from the GNU project web site at: http:// www.gnu.org/copyleft/fdl.html.