Saturday, September 19, 2009

Injecting Gaphor Services

The Gaphor UML modeling tool is more than just a simple diagram editor.  It is also a powerful application architecture, capable of being used outside of the UML context.  What makes it so powerful is that the elements that make up Gaphor are clearly separated into services, components, and adapters.  The Gaphor architecture is important in how it glues all these pieces together.

Gaphor is built on top of several services that support the application as a whole.  There are many required services that are distributed along with Gaphor.  For example, there is an element factory service which is responsible for creating and managing the various UML elements.  These services are then loaded during the Gaphor startup process by iterating through entry points and instantiating the service classes.  This, in fact, is how other Python packages would define Gaphor services.

These services also work the other way around;  existing services can be used by other Python applications instead of defining the service for Gaphor to use.  The services can be used by other applications by invoking the Gaphor injection mechanism.  There are a few precautions to take when using this mechanism and they are illustrated in the example below.

#Example; Gaphor service injection.

#Do the Gaphor imports.
from gaphor.core import Application, inject
from gaphor.UML import Class

#A class is required in order to store the injected service
#as a class attribute.
class Gaphor(object):
    
    #Inject the element factory service.
    element_factory = inject('element_factory')
    
    #Initialize the application which will,
    #in turn, initialize the services.
    def __init__(self):
        Application.init()

#Main
if __name__=="__main__":
    
    #This will not work.  It serves as an illustration as to
    #why a class attribute is necessary.
    try:
        print inject('element_factory').create(Class)
    except:
        pass
    
    #This will work.  First, create and initialize the
    #Gaphor application singleton.  Next, interact with
    #the element factory service.
    app=Gaphor()
    print app.element_factory.create(Class)