• No results found

Proxy home

3.2.6 Composition structure

A composition binds all of the previously-described elements together, and requires that the relationships between the bound entities define a consistent whole.

Note that a component home type necessarily implies a component type; that is, the managed component type specified in the home definition. Likewise, an abstract storage home implies an abstract storage type. It is unnecessary, therefore, for a composition to explicitly specify a component type or an abstract storage type. They are implicitly determined by the specification of a home and abstract storage home.

It may seem odd that the center of focus for compositions is the home rather than the component, but this works out to be reasonably intuitive in practice. The home is the primary point of contact for a client, and the homeÕs interface and behavior have a major influence on the interaction between the client and the component.

A composition definition specifies a name that identifies the composition within the enclosing module scope, and which constitutes the name of a scope within which the contents of the composition are contained. The essential parts of a composition definition are the following:

¥

The name of the composition.

¥

The life cycle category of the component implementation, either service, session, process, or entity, as defined in Section 4.1.4, ÒComponent Categories,Ó on page 4-5.

¥

The home type being implemented (which implicitly identifies the component type being implemented).

¥

The name of the home executor to be generated.

¥

The name of the component executor skeleton to be generated. A composition definition has the following essential form: composition <category> <composition_name> {

home executor <home_executor_name> { implements <home_type> ;

manages <executor_name>; };

};

where <composition_name> is the name of the composition, <category> identifies the life cycle category supported by the composition, <home_executor_name> is the name assigned to the generated home executor skeleton, <home_type> is the name of a component home type imported from IDL, and <executor_name> is the name assigned to the generated component executor skeleton.

This is a schematic representation of the minimal form of a composition, which specifies no state management. The structure of the composition specified by this schematic is illustrated in Figure 3-1. Note that the component type itself is not explicitly specified. It is unambiguously implied by the specification of the home type, as is the relationship between the executor and the component (i.e., that the executor implements the component).

.

Figure 3-1 Minimal composition structure and relationships

General disclaimer and abdication of responsibility with regards to pro- gramming examples:

Before presenting programming examples, it should be noted that all exam- ples are non-normative illustrations. In particular, the implementations provided in the examples of code that is to be generated by the CIF are merely schematic representations of the intended behaviors; they are by no means indicative of the actual content of a real implementation (e.g., they generally donÕt include exception handling, testing for validity, etc.). Although the grammar for CIDL has not been presented yet, a simple example will help illustrate the concepts described in the previous sections. Assume the following IDL component and home definitions:

--- // Example 1 // // USER-SPECIFIED IDL // module LooneyToons { interface Bird {

void fly (in long how_long); };

interface Cat {

void eat (in Bird lunch);

};

component Toon { CIDL

IDL

composition <category> <composition_name> { home executor <home_executor_name> implements <home_type>;

provides Bird tweety; provides Cat sylvester;

};

home ToonTown manages Toon {};

};

--- The following example shows a minimal CIDL definition that describes an implementation binding for those IDL definitions:

--- // Example 1 // // USER-SPECIFIED CIDL // import ::LooneyToons; module MerryMelodies {

// this is the composition:

composition session ToonImpl { home executor ToonTownImpl {

implements LooneyToons::ToonTown; manages ToonSessionImpl; }; }; }; --- In this example, ToonImpl is the name of the composition. It defines the name of the generated home executor to be ToonTownImpl, which imple- mented the ToonTown home interface imported from IDL. The home exec- utor definition also specified the name of the component executor,

ToonSessionImpl, which is managed by the home executor. Note that the component type (Toon) is not explicitly namedÑit is implied by the specifi- cation of the home ToonTown, which is known to manage the component type Toon. Thus, the declaration Òmanages ToonSessionImplÓ implic- itly defines the component executor ToonSessionImpl to be the implemen- tation of the component type Toon.

This CIDL specification would cause the generation of the following arti- facts:

¥ The skeleton for the component executor ToonSessionImpl

¥ The complete implementation of the home executor ToonTownImpl

We provide the following brief sketches of generated implementation skele- tons in Java to help illustrate the programming model for component implementations.

Java <interface>Operations interfaces for all of the IDL interfaces are generated, precisely as currently specified by the current Java IDL lan- guage mapping:

--- // Example 1

//

// GENERATED FROM IDL SPECIFICATION: //

package LooneyToons;

import org.omg.Components.*; public interface BirdOperations {

public void fly (long how_long); }

public interface CatOperations { void eat(LooneyToons.Bird lunch); }

public interface ToonOperations extends CCMObjectOperations {

LooneyToons.Bird provide_tweety(); LooneyToons.Cat provide_sylvester(); }

public interface ToonTownExplicitOperations extends CCMHomeOperations { }

public interface ToonTownImplicitOperations extends KeylessCCMHomeOperations {

Toon create(); }

public interface ToonTownOperations extends ToonTownExplicitOperations,

ToonTownExplicitOperations {}

--- The ToonImpl executor skeleton class has the following form:

--- // Example 1

//

// GENERATED FROM CIDL SPECIFICATION: //

package MerryMelodies; import LooneyToons;

import org.omg.Components.*;

abstract public class ToonSessionImpl

implements ToonOperations, SessionComponent, ExecutorSegmentBase

{

// Generated implementations of operations // inherited from SessionComponent and // ExecutorSegmentBase are omitted here. //

protected ToonSessionImpl() { // generated implementation ... }

// The following operations must be implemented // by the component developer:

abstract public BirdOperations _get_facet_tweety();

abstract public CatOperations _get_facet_sylvester(); }

--- The generated executor abstract base class ToonSessionImpl imple- ments all of the operations inherited by ToonOperations, including opera- tions on CCMObject and its base interfaces. It also implements all of the operations inherited through SessionComponent, which are internal operations invoked by the container and the internals of the home imple- mentation to manage executor instance lifecycle.

A complete implementation of the home executor ToonTownImpl is gener- ated from the CIDL specification:

--- // Example 1

//

// GENERATED FROM CIDL SPECIFICATION: //

package MerryMelodies; import LooneyToons;

import org.omg.Components.*; public class ToonTownImpl

implements LooneyToons,ToonTownOperations, HomeExecutorBase, CCMHome

{

// Implementations of operations inherited // from ExecutorBase and CCMHome

// are omitted here. //

// ToonHomeImpl also provides implementations // of operations inherited from the component // home interface ToonTown

CCMObject create_component() {

return create(); }

void remove_component(CCMObject comp) {

}

}

// and so on... }

--- The user-provided executor implementation must supply the following: ¥ Implementations of the operations _get_tweety and

_get_sylvester, which must return implementations of the BirdOperations and CatOperations interfaces ¥ said implementations of the behaviors of the facets tweety and

sylvester, respectively

The following example shows one possible implementation strategy: ---

// Example 1 //

// PROVIDED BY COMPONENT PROGRAMMER: //

import LooneyToons.*; import MerryMelodies.*;

public class myToonImpl extends ToonSessionImpl implements BirdOperations, CatOperations {

protected long timeFlown; protected Bird lastBirdEaten; public myToonImpl() {

super(); timeFlown = 0; lastBirdEaten = nil; }

public void fly (long how_long) { timeFlown += how_long);

}

public void eat (Bird lunch) { lastBirdEaten = lunch; }

public BirdOperations _get_facet_tweety() { return (BirdOperations) this;

}

public CatOperations _get_facet_sylvester() { return (CatOperations) this;

} }

--- This simple example implements all of the facets directly on the executor. This is not the only option; the programming objects that implement

BirdOperations and CatOperations could be constructed separately and managed by the executor class.

vide is an extension of the home executor that acts as a component executor factory, by implementing the create_executor_segment method. This class must also provide an implementation of a static method called

create_home_executor that returns a new instance of the home executor (as an ExecutorSegmentBase). This static method acts as an entry point for the entire composition.

--- // Example 1

//

// PROVIDED BY COMPONENT PROGRAMMER: //

import LooneyToons.*; import MerryMelodies.*;

public class myToonTownImpl extends ToonTownImpl {

protected myToonTownImpl() { super(); } ExecutorSegmentBase

create_executor_segment (int segid) { return new myToonImpl();

}

public static ExecutorSegmentBase create_home_executor() {

return new myToonTownImpl(); }

}

--- Note that these last two classes constitute the entirety of the code that must be supplied by the programmer. The implementations of operations for nav- igation, executor activation, object reference creation and management, and other mechanical functions are either generated or supplied by the container.