DPML
DPML Central
HomeUtilitiesStationMetro
Freight Train
Parts of a component ...

In classic Metro we use the composition api as the framework for dynamic management. In Metro FT this is replaced by a Parts inner interface and another set of method patterns supporting instance management, deployment and release.

The following source code is from the class ExampleContainer. It is basically the same as ExampleComponent except that we have included the Dimension as a part. As a part the Dimension context is accessible to the containing component (ExampleContainer) and we can get in there are do things based on current state.

package net.dpml.composition.testing;

import java.util.logging.Logger;

public class ExampleContainer implements Example
{
    private final Logger m_logger;
    private final Context m_context;
    private final Parts m_parts;

    public ExampleContainer( final Logger logger, final Context context, final Parts parts )
    {
        m_logger = logger;
        m_context = context;
        m_parts = parts;
    }

    public void doMyStuff()
    {
        //
        // configure the dimension component's context map
        //

        Map map = m_parts.getDimensionContextMap();
        int width = m_context.getWidth( 9 );
        int height = m_context.getHeight( 7 );
        map.put( "height", new Integer( height ) );
        map.put( "width", new Integer( width ) );

        //
        // get the dimension instance
        //

        Dimension dimension = m_parts.getDimension();
        int size = dimension.getSize();
        m_logger.info( 
          "Creating a widget with a area of " + size );
    }


    public interface Context extends DimensionalContext{}

    public interface Parts
    {
        Map getDimensionContextMap();
        Dimension getDimension();
    }
}

The parts of component are distinct from context in that parts are exclusivly managed by the containing component. In the above example the Dimension component model is declared in XML and the component is reaching into the context model of the Dimension component and modifying height and width values based on it's own context information. After modification of the context the component acquires an instance of Dimension and proceeds with service execution.

The formal patterns associated with a Parts inner interface deal with default and identifiable instances.

Methods dealing with the default instance include:

   [type] get[key]();                     // return the default service instance
[manager] get[key]ContextManager();       // return the context manager for the default instance
      Map get[key]ContextMap();           // return the context map for the default instance
Component get[key]Component()             // return a model of a Component instance
    Model get[key]Model()                 // return the Model of a component type

Methods dealing with the identifiable instance include:

   [type] get[key]( [id] );               // return an identified service instance
   [type] get[key]( [id], [policy] );     // same as above with control over proxy creation
[manager] get[key]ContextManager( [id] ); // return the context manager for the identified instance
      Map get[key]ContextMap( [id] );     // return the context map for the identified instance
Component get[key]Component( [id] )       // return a model of an identified Component instance
    Model get[key]Model( [id] )           // return the Model of an identified component type

In addition to the above the following optional release method signature is supported:

     void release[key]( [instance] )         // release of a proxy or implementation instance

In the above examples we are interacting with the context model of the Dimension component via the java.util.Map interface. As suggested by the [manager] get[key]ContextManager( [id] ); a type safe management strategy is also provided as demonstrated in the following code fragment:

    public void doMyStuff()
    {
        DimensionalContext.Manager manager = 
          m_parts.getDimensionContextManager();
        manager.setHeight( height );
        manager.setWidth( width );

        Dimension dimension = m_parts.getDimension();
        int size = dimension.getSize();
        m_logger.info( 
          "Creating a widget with a area of " + size );
    }

    public interface Parts
    {
        DimensionalContext.Manager getDimensionContextManager();
        Dimension getDimension();
    }

Where DimensionContext and the associated inner Manager are defined as:

public interface DimensionalContext
{
    int getHeight( int h );
    int getWidth( int w );

    interface Manager extends DimensionalContext
    {
        void setWidth( int width );
        void setHeight( int height );
    }
}

In effect the Parts interface and its associated patterns provide a framework for management of internal parts with minimal API intrusion (significantly reducing the OS risk factor).

Parts within parts ...

The following part descriptor demonstrates the creation of a part containing another part within itself. Nested parts are declared within the <parts> element. Support for custom part handlers is provided at the build level, allowing for example the inclusion of a completely foreign part as a intrinsic part of the containing part. This feature will enable 'radical' development of the metro platform while retaining runtime compatibility with prior releases.

The part descriptor:

    <component dest="target/test/acme-example-three.part" 
        xmlns="plugin:dpml/composition/dpml-composition-builder" 
        type="net.dpml.composition.testing.ExampleContainer"
        name="demo">
      <parts>
        <component key="dimension" type="net.dpml.composition.testing.DimensionComponent"/>
      </parts>
    </component>
Parts by reference ...

In addition to the classic declaration of parts - support has been included for parts-by-reference. The following <component> delcaration has a <parts> element that is using the <part> element to include a foreign part by reference to a Transit artifact uri.

    <x:property key="dpml-composition-testing-acme" feature="uri" type="part" name="acme.uri"/>
    <component dest="target/test/acme-example-four.part" 
        xmlns="plugin:dpml/composition/dpml-composition-builder" 
        type="net.dpml.composition.testing.ExampleContainer"
        name="demo">
      <parts>
        <part key="dimension" uri="${acme.uri}"/>
      </parts>
    </component>
Observations, issues and questions ...

While the current development effort is looking promising there are number of issues still to addressed. These topics are covered in the following section.