Monday, 21 September 2009

Week 38 of 2009

I started this week by finishing off the view factory logic I mentioned last week. I discovered that Java reflection and generics don't mix well! The old factory logic used reflection to create a view using a standard constructor. However, I had to change all the view constructors to reference their model elements generically. Unfortunately, you don't seem to be able to create the generic parameters that are required to invoke the constructors using reflection. I've probably just missed something really simple! Anyway, I decided to implement the factory longhand using a big switch statement. A big advantage of this approach is that the compiler can check the constructors exist at compile time. The only disadvantage is the big and ugly switch statement.

The next thing I did was a total sidetrack but a useful improvement. I've extracted all notation specific object/role names from model elements into an OOA Dictionary. The dictionary provides the Shlaer-Mellor, Executable UML (xtUML) and Executable UML2 (xtUML + UML2) names and icons for all object/role names. The OOA Dictionary webpage just referenced is automatically generated from OOA Tool rather than manually maintained. This means that each future build will allow the user to browse the dictionary that is specific to that build since these names (and icons) are still evolving. I've also added the dictionary as a resource to the main website. However, this will always contain the latest version of the dictionary which may differ from that used in any given OOA Tool build.

A very interesting possibility now that I have a notation switchable dictionary within OOA Tool is that I could use it to convert any OOA of OOA within OOA Tool to use Executable UML terminology. I will need to extend the dictionary to include attribute names, verb phrases and role names. However, the vast majority of these either overlap the object/role names or won't need to be changed. Diagrams do need to be scaled after these conversions. However, I could determine appropriate defaults so that completely changing notation on a loaded metamodel is a one click action.

An even more interesting possibility is that I will be able to generate Executable UML metamodel populations so that archetype templates can reference Executable UML classes and attributes rather than Shlaer-Mellor objects and attributes. For example, the following simple archetype template which generates a list of qualified object names:

.select many objects from instances of Object
.for each object in objects
.select one domain related by \
    object->Information_Model->Domain
Object: ${domain.Name}.${object.Name}
.end for
.emit to file "ObjectList.txt"
could alternatively be coded as:
.select many classes from instances of Class
.for each class in classes
.select one domain related by \
    class->PlatformIndependentModel->Domain
Class: ${domain.name}.${class.name}
.end for
.emit to file "ClassList.txt"

OK, so what's next. I need to finish the OOA Dictionary webpage generator and ensure that all views reference the dictionary rather than hardcode notation specific labels. I also need to add a menu item (on the Help menu) for viewing a build specific dictionary within OOA Tool. After that I'm not sure since my To Do List is way too big and I seem to be picking items at random at the moment! I would like to hear from people with regards to what UML/UML2 names I should be using within the OOA Dictionary since I wouldn't claim to be an expert on UML terminology since it keeps changing!

Monday, 14 September 2009

Week 37 of 2009

Java SE 6 executable Jar files don't seem to be limited to 64M on Vista x64 which means that running OOA Tool by clicking the Jar is probably better in the next release than running the Batch or Shell scripts that I also include in releases since event logging is now captured and viewable within OOA Tool. After some checking via Google, I discovered that executable Jar files can be executed with any JVM options by altering the following registry entry on Windows:


HKEY_CLASSES_ROOT\jarfile\shell\open\command
The current value on my machine is:

"C:\Program Files\Java\jre6\bin\javaw.exe" -jar "%1" %*
Changing this to the following increases maximum memory to 256M:

"C:\Program Files\Java\jre6\bin\javaw.exe" -Xmx256M -jar "%1" %*
However, this step doesn't seem to be necessary on Vista x64 since OOA Tool starts up with 903M by default on my machine! I'm not sure what you need to change to do the same thing on a Mac or under Unix.

My JBuilder 2005 IDE finally seems to be having problems building OOA Tool by itself. I have already had to work around some nasty JBuilder bugs, e.g. you can't break or continue directly out of a nested loop since JBuilder generates some shit bytecode that doesn't work. Note that all releases are built using an Ant build file and the latest JDK so these problems only effect me since I want to be able to instrument and step thru code using the JBuilder debugger. The latest problem seems to be related to too much complexity involving Java Generics. The JDK builds all of my stuff without a single warning (although I do have to use a few @SuppressWarnings("unchecked") directives). I can even build my stuff using JBuilder itself if I build all packages bar one first and then build the last package afterwards!

I have considered upgrading JBuilder to the latest version except they have moved JBuilder onto the Eclipse platform which means I will have to learn the Eclipse IDE to use it. If I'm going to learn Eclipse I don't see what additional benefits I would get from buying JBuilder since I'm not currently a Java Enterprise user. I also don't use JBuilder's GUI builder. If Embarcadero Technologies wants users like me to move to the latest version then they need to make the Professional version of the tool cheaper or they need to provide a Foundation version for free like they did in the past.

I mentioned Vista for the first time at the beginning of this blog because I have recently bought a new laptop (my old laptop kept overheating and shutting down). It's the first machine I have had with Vista, previous machines have all been running XP instead. It's also the first 64 bit machine I have had so I can now see how well Java x64 runs. There doesn't seem to be any problems running OOA Tool. A screenshot from my laptop is shown below:

From the screenshot, you can see that load times are longer in the latest build. This is a consequence of a safer model element design and the fact that I haven't spent any time optimizing load times yet. Most users will not need to load more than one project on startup so load times should not be more than a few seconds anyway.

One big drawback with Vista is that I can't get JBuilder 2005 to even install never mind run. I've tried copying the installed directory over from my desktop machine (as recommended by other developers in my position) but it still doesn't run. It looks like I will have to move to Eclipse once my desktop machine packs in.

OK, so what have I been doing other than messing with Vista and JBuilder this week? I have spent most of the week refactoring an application wide factory into OOA Tool. The existing design included two types of factory: model element factory methods which are defined on parent model elements (e.g. OOAObject class defines a createAttribute() method), and editor view factory methods which create an appropriate form/diagram/table/report view for a given model element. To debug OOA Tool I often have to tweek methods in various model elements to determine what's happening. I also have to add workarounds for backwards compatility. However, I really want to be able to subclass model elements when debugging and move any backwards compatibility code out of the main model element classes into subclasses. To do this with the current design requires subclassing at several levels, e.g. to create a new Attribute subclass we need to create new OOAObject, InformationModel, Domain and Project classes since creation is delegated at each level.

The solution on the model element side was to add a factory reference to all model elements. Root elements are passed a factory but have no parent. Non-root elements are passed a parent and optionally passed a factory. If no factory is given then a non-root element uses the factory of the parent. I also wanted to statically scope factories using Generics so the new signature of the ModelElement class is given below along with a brief outline of OOAObject:


public interface ModelElementFactory { }

public abstract class ModelElement<F extends ModelElementFactory,
                                   P extends ModelElement<F, ?> {
    private F m_factory;

    protected ModelElement(P parent, F factory, boolean deleted) {
        if (factory == null) {
            throw new NullPointerException("Factory required");
        }
        // ...
    }

    protected ModelElement(F factory) { // Root element constructor
        this(null, factory, false);
    }

    protected ModelElement(P parent) { // Non-root constructor
        this(parent, (parent != null) ? parent.getFactory() : null,
             true);
    }

    public final F getFactory() {
        return m_factory;
    }
}

public interface OOAFactory extends ModelElementFactory {
    public Attribute createAttribute(OOAObject parent);
}

public class OOAObject<F extends OOAFactory>
        extends ModelElement<F, InformationModel<F>> {
    public OOAObject(InformationModel<F> parent) {
        super(parent);
    }

    public Attribute createAttribute() {
        return getFactory().createAttribute(this);
    }
}

I'll leave this weeks report there since we seem to be getting a little bit technical with all this Java coding! Hopefully, I'll have more modelling specific stuff to report next week.

Monday, 7 September 2009

Week 36 of 2009

A few distractions derailed this week's activities since they gave me some thinking time and I came up with a few new ideas! The main one being to merge in some Swing components that I developed just prior to starting this project. These components included: a console and I/O library for interactive console-like editor panes, an enhanced event logger (mostly internal benefits), and a status bar panel. I have now added a consoles tabbed pane at the bottom of OOA Tool and a status bar panel right on the bottom edge.

The consoles tabbed pane will always contain a System Log of colour-coded events which were previously sent to standard output. The System Log is highly configurable with many filtering and formatting options. It also allows logs to be saved as XML files. You will also be able to create command consoles for interacting with operating system specific shell environments. Simulation and translation logs will also appear here in the future.

The status bar includes a message area, a locale indicator (language only) and a clock. The main user of the status bar at present is the model element browser which displays the currently selected element in the status bar. Since the browser is normally given very little width, many elements will not be entirely visible in the browser. The status bar provides an easy way to see longer elements, i.e. just select the element. Both screenshots below demonstrate this.

The following screenshot shows OOA Tool (using the Java SE 6 Nimbus look and feel) after the Object.Prominent attribute has been changed (notice the pencil on the attribute's icon):

The following screenshot shows log messages at different levels in different colours (demonstrating some current BP loading problems!):

This new distraction has left a few loose ends to resolve. I need to do a sweep thru the code base ensuring that only the new event logger is used. I need to add a new View menu to the menu bar allowing some control over which panes are visible beyond the split pane controls. I also need to check the new components don't have any problems using the Nimbus look and feel. An ability to select locale will also be added.

I also need to think about resource bundle usage (for multiple language support) within OOA Tool since the new components already ultilize them. The main problem here if we want to fully support other languages is that Shlaer-Mellor and Executable UML names are very carefully thought out and controlled, more so than normal user interface titles and messages. Does anyone out there have any views with regard to additional language support? What do French, German, Russian, Japanese, Chinese etc. modellers want to see - English or their own language? Are there any UML tools out there that convert the UML metamodel into non-English for non-English users?

Monday, 31 August 2009

Week 35 of 2009

Most of this week I have been finishing the changes that I started last week - the last 20% always takes longer than you expect! I have also been resolving some imported shape problems in Object Model diagrams (OIMs, OCMs and OAMs). Skip over the next few paragraphs for details.

One of the problems I discovered (in that last 20%!) was how responsive deleted model elements need to be while a project is being loaded. One of the changes I made was to stop deleted model element listeners from doing anything except awaiting a request to clear their deleted status. This reduces unnecessary derived calculations and stops listeners from expanding their listening scope until after their deleted status is cleared. The problem that I discovered was that some derived fields must be calculated so that cross references during loading can be resolved prior to those model elements having their deleted status cleared.

A massively cut down version of the Identifier class is shown below to highlight current listener design and the problem I mention above:


public class Identifier extends ModelElement<OOAObject>
        implements OrderedElement<OOAObject> {

    public static final String IDENTIFIER_ID_PROPERTY = "identifierID";

    public IdentifierListener implements PropertyChangeListener {
        public IdentifierListener() {
            checkDeleted();
        }

        protected void checkDeleted() {
            if (isDeleted()) {
                for (Attribute attribute : m_identifyingAttributes) {
                    attribute.removePropertyChangeListener(this);
                }
            } else {
                for (Attribute attribute : m_identifyingAttributes) {
                    attribute.addPropertyChangeListener(this);
                }
                setBrowserLabel();
            }
        }

        public void propertyChange(PropertyChangeEvent event) {
            Object source = event.getSource();
            String propertyName = event.getPropertyName();
            if (source == Identifier.this) {
                if (propertyName == DELETED_PROPERTY) {
                    checkDeleted();
                } else if (propertyName == ORDER_PROPERTY) {
                    setIdentifierID();
                } else if (isDeleted()) {
                    // Do nothing else if deleted
                } else if (propertyName == IDENTIFIER_ID_PROPERTY) {
                    setBrowserLabel();
                } else if (propertyName == IDENTIFYING_ATTRIBUTE_PROPERTY) {
                    Object oldValue = event.getOldValue();
                    if (oldValue instanceof Attribute) {
                        ((Attribute) oldValue)
                            .removePropertyChangeListener(this);
                    }
                    Object newValue = event.getNewValue();
                    if (newValue instanceof Attribute) {
                        ((Attribute) newValue)
                            .addPropertyChangeListener(this);
                    }
                    setBrowserLabel();
                }
            } else if (source instanceof Attribute) {
                if (propertyName == Attribute.NAME_PROPERTY
                        || propertyName == Attribute.ORDER_PROPERTY) {
                    setBrowserLabel();
                }
            }
        }
    }

    private int m_order; // Set by parent object
    private String m_identifierID;
    private Identifier[] m_identifyingAttributes;

    public Identifier(OOAObject parent) {
        super(parent);
        m_order = 0;
        m_identifierID = "";
        m_identifyingAttributes = Attribute.EMPTY_ATTRIBUTES;
        addPropertyChangeListener(new IdentifierListener());
    }

    public final String getIdentifierID() {
        return m_identifierID;
    }

    public void setIdentifierID() {
        int order = m_order;
        if (order == 0) {
            return;
        }
        String identifierID = (order == 1) ? "I" : "I" + order;
            // Don't use order if 1 since "I1" looks confusing
        String oldIdentifierID = m_identifierID;
        m_identifierID = identifierID;
        fireDerivedChange(IDENTIFIER_ID_PROPERTY,
                          oldIdentifierID, identifierID);
    }
}
Since identifier ID is used to reference target identifiers within participant mappings then it must be calculated even if identifier is currently deleted. However, the identifier ID calculation which depends on order being set by a parent OOAObject still requires the identifier to have been added to the parent object.

From the example above, you can see that all model elements have a model element instance and a separate listener instance (sometimes more than one). The listener drives all derived calculations and arranges for the spread of itself to other instances of interest. The new deleted status is used to control all such listeners but some derived calculations must continue independent of the deleted status. This is a consequence of using mathematically dependent attributes in preferred identifiers. I'm sure this is going to be an interesting problem to solve when I start creating my model compiler!

I can't remember whether I've already mentioned a name change (that I made some time ago) from Terminator to External Entity. The original Shlaer-Mellor books used both terms and I adopted the term Terminator (short and sweet!). However, other tool vendors all adopted the term External Entity instead. I later introduced an Entity supertype object above Terminator and Object. I finally decided to bite the bullet and replace all use of the term Terminator with External Entity. Both iUML and BridgePoint still use the term External Entity as a kind of Actor. However, OOA Tool simply uses Actor instead of External Entity when Executable UML notation is selected.

The problem with imported shapes is that imported objects (in OIMs), imported state models (in OCMs/OAMs) and external entities (in OCMs/OAMs) without links to other shapes on those diagrams are not reimported when a project is loaded. The original justification being that those shapes must be redundant. However, I now reimport those shapes if they exist in the XML project file. I have also added some extra actions to the OCM and OAM diagram editor to allow users to add existing external entities to those diagrams and remove them from specific diagrams. Obviously, external entities which have links to other shapes can't be removed. Once the next build is released I will have to update the various technical notes discussing OIMs, OCMs and OAMs.

A related issue is Subsystem Model diagrams (SCMs and SAMs) which don't currently show external entities at all. However, I think I will allow users to add external entities allowing subsystem communications/accesses to those external entities to be shown. I debated this issue with myself when I first coded the editors for those diagrams and I decided to stick with what is shown in the original Shlaer-Mellor books. However, I like the idea of being able to see subsystem communications/accesses to external entities and I think I will take advantage of the above change that I made with regard to reimporting shapes during project loading. However, I haven't coded this up yet.

Now, I have some loose ends to sort out and I need to finish off the technical note on identifiers but then I will refocus myself on the outstanding items required to get Build 014 released. I remember the days when I had a team working for me and I could delegate (sweet...)!

Monday, 24 August 2009

Week 34 of 2009

This week I started with a nice Costa coffee (I like Starbucks but their cafe in Colchester has unfriendly staff and poor seating). I should have been nailing down the outstanding issues holding back Build 014 of OOA Tool. Instead, I had a think about some of the annoying design decisions I made when I started creating the model elements that realize the OOA of OOA within OOA Tool.

One of the most annoying (for me) is that I associate a dynamic parent with each model element. On reflection, a static unchanging parent is much safer and entirely acceptable for OOA Tool. You might not think it makes much difference. However, there is an enormous amount of listener code within these model elements allowing derived fields to push their changes out to GUI listeners which update the GUI as and when changes occur. There is also lots of unnecessary parent status checking. I also take advantage of the fact that the parent of a child is cleared when it is removed from the parent. Of course, removing the parent can cause problems with the deleted model elements which may still be in use! Thankfully, programmer deletion is logical rather than physically in Java so I don't need to worry about memory being reclaimed while still in use.

I also associate a changed status with each model element which I recursively clear after a project is loaded or saved. However, I hadn't got around to setting the changed status when non-derived fields are changed. An annoying side-effect of this was that I couldn't check whether any projects had been changed when the application is exited, i.e. a confirmation dialog is always popped up - very annoying.

A cut down outline of the ModelElement class is shown below:


public abstract class ModelElement {
    private ModelElement m_parent;
    private boolean m_changed;

    protected ModelElement() { }

    public ModelElement getParent() { }
    public void setParent(ModelElement parent) { }
    public abstract ModelElement[] getChildren();

    public boolean isChanged() { }
    public void setChanged(boolean changed) { }
    public boolean isChangedAnywhere() { }
    public void setChangedRecursively(boolean changed) { }

    protected void firePropertyChange(String propertyName,
            ModelElement oldValue, ModelElement newValue,
            boolean child) {
        if (oldValue != newValue) {
            m_propertyChangeSupport.firePropertyChangeEvent(
                propertyName, oldValue, newValue);
            if (child) {
                if (oldValue != null) {
                    oldValue.setParent(null);
                }
                if (newValue != null) {
                    newValue.setParent(this);
                }
            }
        }
    }
}

A cut down outline of the new improved ModelElement class is shown below:


public abstract class ModelElement<P extends ModelElement> {
    private P m_parent;
    private boolean m_deleted;
    private boolean m_changed;
    private boolean m_changedAnywhere;

    protected ModelElement(P parent) { }

    public P getParent() { }
    public abstract ModelElement[] getChildren();

    public boolean isDeleted() { }
    public void setDeleted(boolean deleted) { }
    public void setDeletedRecursively(boolean deleted) { }

    public final boolean isChanged() {
        return m_changed;
    }
    public void setChanged(boolean changed) {
        boolean oldChanged = m_changed;
        if (changed != oldChanged) {
            m_changed = changed;
            m_propertyChangeSupport.firePropertyChange(
                CHANGED_PROPERTY, oldChanged, changed);
            ModelElement modelElement = this;
            while (modelElement != null) {
                modelElement.setChangedAnywhere();
                modelElement = modelElement.getParent();
            }
        }
    }
    public final boolean isChangedAnywhere() {
        return m_changedAnywhere;
    }
    public void setChangedAnywhere() {
        boolean changedAnywhere = m_changed;
        if (!changedAnywhere) {
            for (ModelElement child : getChildren()) {
                if (m_child.m_changedAnywhere) {
                    changedAnywhere = true;
                    break;
                }
            }
        }
        boolean oldChangedAnywhere = m_changedAnywhere;
        m_changedAnywhere = changedAnywhere;
        m_propertyChangeSupport.firePropertyChange(
            CHANGED_ANYWHERE_PROPERTY,
            oldChangedAnywhere, changedAnywhere);
    }
    public void setChangedRecursively(boolean changed) {
        setChanged(changed);
        for (ModelElement child : getChildren()) {
            child.setChangedRecursively(changed);
        }
    }

    protected void firePropertyChange(String propertyName,
            ModelElement oldValue, ModelElement newValue,
            boolean child, boolean derived) {
        if (oldValue != newValue) {
            m_propertyChangeSupport.firePropertyChangeEvent(
                propertyName, oldValue, newValue);
            if (child) {
                if (oldValue != null && !m_deleted) {
                    oldValue.setDeletedRecursively(true);
                }
                if (newValue != null && !m_deleted) {
                    newValue.setDeletedRecursively(false);
                }
            }
            if (!derived && !m_deleted) {
                setChanged(true);
            }
        }
    }
}

This requires parents to be statically declared using Java generics and requires the parent to be passed to the constructor. The only root element without a parent being a Project in OOA Tool. However, it is still useful to know when a model element is removed so a new deleted status was added. The setting and clearing of this status is done when property changes are fired. I have also been able to clear up some minor memory leaks by making use of the deleted status to add or remove nested listeners in line with the deleted status.

I also added another flag to firePropertyChange() indicating whether a derived change has occurred. This allows us to set changed statuses automatically as a consequence. Since we have a fixed parent now we can also fairly easily determine a changed anywhere status for each model element where anywhere indicates at or below a given model element. The old design required a recursive check to be performed on request to determine whether changed anywhere. OOA Tool now adds a changed (or changed anywhere) overlay icon to tree browser icons when changed or changed anywhere statuses are updated. It can also be determined if any projects have changed when the user exits the application, i.e. no redundant dialog. However, there is a limitation here in that if a change is made and another change follows it which undoes the previous change, the model element will still be flagged as changed. This doesn't occur in any of the editor dialogs since they record the original values and always check the current values against the original values when determining whether a change has occurred.

These changes (80% done now) were for the most part straight forward except for the fact that there are 336 model element classes (744 classes in total)! However, there were a few places where I unnecessarily took advantage of dynamic parents and this code needed to be rewritten.

OK, this was a serious side-track from my current priorities. However, I am very happy with the changed and changed anywhere indicators in the tree browser. I am also much happier that the parent is always set now and its type can be statically determined reducing the need for so many casts.

Monday, 17 August 2009

Week 28/29/30/31/32/33 of 2009

OK, back to the Shlaer-Mellor and Executable UML grindstone. I've have a few weeks away from modelling and tooling to clear my head. My highest priority now is to create a stable build to release the many features I have added and changes I have made to OOA Tool. The outstanding issues holding up the release are:

  • reworking OOA of OOA Metamodel 0.01 population logic since I have considerably expanded the Information Model and Data Type subsystems,
  • finishing the outstanding chunks of operation logic including predefined operations on all data types,
  • and reviewing and documenting OOA Interchange Format Version 0.05 since lots of changes have been made (but OOA Tool will still be backwards compatible with Version 0.04).
The next build won't include a working simulator since I'm not happy with all the semantics yet and I don't want people investing time creating Action Language code until I'm happy.

Over the last week, I had a good long look at the subject of object ordering within information models (another diversion!). Complete orderings across child-parent relationships are already handled using Arbitrary ID Attributes and Parent Allocated ID Types (important note to self: finish the technical note on Arbitrary and Ordinal IDs so that people know what I'm talking about!). Partial and complete orderings across objects within Action Language code is handled using an ordered by clause on select statements. However, such orderings are transitory in nature and prone to becoming out of date when an information model changes, e.g. what was once a complete ordering can become a partial ordering without anyone noticing. With regard to complete orderings, the logical place to look in an information model is an identifier since an identifier specifies the minimum information required to define a complete ordering. This lead me to subtype identifiers as either Unordered Identifiers or Ordered Identifiers (see Information Model). Now I'm not going to say too much here since I want to discuss the issues in full in a technical note on Identifiers which I hope to publish soon. However, objects can now define a preferred identifier and an ordered by identifier. If the latter is specified then the object in question is ordered and object instances can be compared using normal relational operators within Action Language code.

This work on ordered identifiers has also allowed me to think how limited but meaningful aggregation and composition relationships could be defined within Executable UML models. Composition relationships could result from child-parent relationships that result directly from Parent Allocated ID Types since those parents have specific duties to manage their children (even though those duties are automatically handled by a software architecture). While aggregation relationships could result from child-parent relationships that result from ordered identifiers. I'm going to add support for hollow and filled diamonds into OOA Tool and see how these ideas work within my example models.

Anyway, I hope to get back to weekly reporting now. If anyone wants to discuss any ideas then don't be shy.

Tuesday, 7 July 2009

Week 26/27 of 2009

During the first week, I defined a new type of operation called an operator (unary operator, binary operator or dot operator). Operators are always owned by data types. Unary operators include: not, +, -, empty, not_empty and cardinality. Binary operators include: or, and, ==, !=, <, <=, >, >=, +, -, *, / and %. There are no plans to allow custom operator symbols at present. Dot operators are like object instance processes except that they are invoked on a data value operand rather than an object instance reference. However, all dot operator names must be unique within a data type. OOA09 does not allow any operation name (excluding operator symbols) to be overloaded using different sets of input parameters.

Operators were introduced so that the semantics of predefined operators on core types could be specified within a model. However, they now also allow new data types to be defined with custom semantics for those same unary and binary operators. For example, the Extended Boolean data type mentioned in [DataType97] can now be specified with correct implementations for not, and and or. However, to ensure operators are side-effect free, severe restrictions have been placed on what can be done within an operator body, i.e. operators can't access objects at all, can't generate events and can only invoke other operators.

During the second week, I spent some time nailing down process modelling. Other Shlaer-Mellor and Executable UML tool vendors have taken the view that process modelling adds no value. However, I think that process modelling provides the perfect mechanism for defining concurrent data flows within composed operations. To better facilitate the work, I split the old Process Model subsystem in the OOA Tool Model into a new Operation subsystem and a more focused Process Model subsystem. The Data Dictionary subsystem was also renamed as the Data Type subsystem at the same time. Process models in OOA09 allow concurrent data flows to be safely specified within a composed operation (action or synchronous service) since circular data flows are not allowed. However, most composed operations won't benefit from concurrent data flows and are more easily defined using an Action Language statement block.