• Nenhum resultado encontrado

3.3 Modelo de Projeto CM-tel

3.3.1 Componentes CM-tel

O modelo de projeto para componentes refina o modelo de especificação descrito anteriormente detalhando a estrutura interna fornecida pelo modelo CM-tel para a construção de componentes, bem como para as operações das interfaces correspondentes aos elementos desta estrutura. Esta estru- tura interna contempla um conjunto de artefatos necessários à construção destes componentes. Este conjunto de artefatos forma a infra-estrutura de componentes de software denominada framework de componentes e proporciona um ambiente contextual, isto é, um “mundo do componente” fornecendo o suporte necessário para a instanciação, composição, especialização e execução de componentes nos seus respectivos contêineres. Note que, dependendo dos elementos definidos na especificação de um componente é gerado um framework de componentes contendo os artefatos correspondentes. O framework de componentes, no contexto do paradigma de desenvolvimento orientado a compo- nentes, foi definido na Seção 2.2.9 como uma infra-estrutura que viabiliza a composição e instalação de componentes.

componente CM-tel. Esta é a forma geral, imposta pelo modelo, de como cada um dos elementos da estrutura de um componente CM-tel é realizado. Esta forma consiste de uma fábrica para a instan- ciação da classe que implementa a interface do elemento especificado pelo componente. Esta classe pode necessitar de serviços específicos. Por exemplo, as portas de sinal necessitam de um serviço de notificação, enquanto que as portas de fluxo contínuo necessitam do serviço de controle e gerência de fluxos de mídia contínua. A classe que implementa a interface do elemento pode ainda interagir com parte da aplicação. Por exemplo, uma porta produtora de eventos pode expor uma interface de notificação, onde eventos gerados pela aplicação são notificados (esta notificação gera a emissão de eventos por parte da porta do componente para as portas conectadas de outros componentes). Esta interface de notificação é interna, ou seja, visível apenas aos objetos instanciados no mesmo espaço de endereçamento do componente.

instancia

de Objeto interage do Elemento usa

Fábrica do Elemento Elemento Serviço +create() Aplicação Implementação Interface do

Fig. 3.19: Modelo de projeto para portas e elementos de configuração CM-tel.

Outro aspecto importante é o processo de instanciação de um componente CM-tel, ilustrado na Figura 3.20. Os componentes são instanciados pela fábrica de componentes por meio da operação

create, que serve como uma interface para que os clientes possam gerenciar as instâncias do respectivo

componente. O processo de instanciação mostra que a implementação da operação create instancia, inicialmente, a classe que implementa a interface equivalente do componente. A seguir, para cada porta e elemento de configuração definidos pelo componente, a fábrica de componentes interage com a respectiva fábrica de cada elemento a fim de instanciá-lo. Uma vez instanciado o elemento, este é registrado pela fábrica de cada elemento na classe que implementa a interface equivalente, por meio da operação interna register_element. Este registro é necessário para que a interface equivalente possa retornar a referência do elemento do componente através de suas operações de navegação.

instancia instancia Elemento Fábrica do Elemento usa Equivalente Interface +register_element() +create() registra Componente Fábrica do +create()

Fig. 3.20: Instanciação de componentes CM-tel.

ponente possa ser instanciado e para que possa interagir com o contêiner e com outros componentes, segundo as regras de interação definidas anteriormente, é fornecida pelo framework de componentes CM-tel.

No lado do componente, um framework de componentes CM-tel consiste das seguintes classes:

• fábrica do componente;

• fábrica de cada elemento especificado no componente;

• classes que implementam a interface de cada elemento especificado no componente;

• infra-estrutura para acesso remoto às interfaces do componente (skeletons das interfaces);

• infra-estrutura de acesso aos serviços de objetos (stubs das interfaces dos serviços).

No lado do cliente do componente, um framework de componentes CM-tel consiste das seguintes classes:

• infra-estrutura para acesso remoto às interfaces do componente (stubs das interfaces);

• um conjunto de classes utilitárias para a interação com o componente:

1. classes para navegação (localizadoras de componentes no contêiner);

2. classes para a manipulação de propriedades definidas pelos elementos de configuração do componente.

A seguir é descrito o modelo de projeto para os elementos que compõem o framework de compo- nentes.

Modelo de Projeto para Interface Equivalente

O modelo de projeto para a interface equivalente é apresentado na Figura 3.21. As operações definidas na interface equivalente devem ser realizadas na classe que a implementa (ComponentImpl). Dependendo dos elementos que são especificados no componente é gerado um conjunto diferente de operações. Por exemplo, caso a especificação de um componente contenha um receptáculo, então as operações específicas para o tipo de receptáculo (simples ou múltiplo) são automaticamente geradas na classe ComponentImpl; caso contrário, elas não são geradas.

+get_home() +get_primary_key() +configuration_complete() 1 +provide() +register_element() +set_container() +get_container() +install() +deinstall() ComponentImpl

Fig. 3.21: Projeto da interface equivalente para componentes CM-tel.

A classe ComponentImpl define as seguintes operações:

1. A operação get_home retorna a referência da fábrica que criou o componente, sendo definida em UML como (ObjRef denota a referência para um objeto remoto):

get_home() : ObjRef

Esta operação não lança nenhuma exceção.

2. A operação get_primary_key retorna a chave que identifica o componente, sendo definida em UML como:

get_primary_key() : String

A operação lança a exceção NoKeyAvailable, caso não exista uma chave que identifique esta instância do componente.

3. A operação configuration_complete coloca o componente no estado operacional (apto para interagir com outros componentes), sendo definida em UML como:

configuration_complete() : void

A operação lança a exceção InvalidConfiguration, caso a transição do componente do estado de configuração para o estado operacional seja impossível no momento.

4. A operação provide é uma operação de navegação, a partir da qual os demais elementos estru- turais do componente são acessados, sendo definida em UML como:

provide(name: string) : ObjRef

O parâmetro name fornece o nome do elemento do componente, cuja referência é retornada pela operação. A operação lança a exceção ElementNotFound caso o elemento especificado no parâmetro de entrada não exista.

5. Operações para receptáculos, definidas na Seção 3.3.1.

A classe ComponentImpl implementa três operações de callback invocadas pela fábrica do com- ponente:

1. A operação set_container informa ao componente a referência de seu ambiente de execução (contêiner), sendo definida em UML como:

set_container(cont : Container) : void

2. A operação install informa ao componente que o mesmo foi instalado no ambiente de execução, sendo definida em UML como:

install() : void

3. A operação deinstall informa ao componente que o mesmo está prestes a ser removido de seu ambiente de execução, sendo definida em UML como:

deinstall() : void

A classe ComponentImpl implementa ainda duas operações internas:

1. A operação register_element registra o elemento instanciado na interface equivalente, sendo definida em UML como:

register_element(name : string, element : ObjRef) : void

A operação recebe como parâmetros o nome do elemento e a referência de sua interface, e lança a exceção InvalidName, caso o nome ou referência do elemento sejam inválidos (por exemplo, nulos).

2. A operação get_container retorna a referência do ambiente de execução do componente, sendo definida em UML como:

Modelo de Projeto para Fábrica de Componentes

A Fábrica de Componentes (ComponentHome) consiste em um objeto que expõe uma interface que define operações de gerência do ciclo de vida de um componente CM-tel tais como operações para criar, encontrar e destruir instâncias dos componentes hospedados no contêiner. Este elemento gerencia o conjunto de todas as instâncias de um tipo específico de componente.

A representação da fábrica de componentes CM-tel é ilustrada na Figura 3.22.

ComponentHomeImpl Home +create() +remove() +find_by_primary_key() ComponentHome +get_primary_key() Component <<component>>

Fig. 3.22: Fábrica de componentes CM-tel (ComponentHome).

A interface ComponentHome deriva de uma interface base, Home. A interface Home consiste da base a partir da qual são derivadas as fábricas dos elementos do contêiner como, por exemplo, a fábrica de componentes ComponentHome e a fábrica de agentes AgentHome. A interface Home não define operações. A classe ComponentHomeImpl implementa a interface ComponentHome e exporta quatro operações:

1. A operação create permite criar uma nova instância de um componente que será gerenciada pela sua fábrica de componentes. Esta instância é identificada pela chave primária que é passada como parâmetro da operação. As chaves primárias servem para identificar as instâncias de um componente. Esta operação retorna a interface equivalente do componente e possui a seguinte definição em UML:

create(key : string) : ObjRef

Esta operação lança as exceções: InvalidKey, caso a chave primária passada como parâmetro da operação seja inválida e DuplicateKeyValue, caso já exista uma instância de componente associada à chave fornecida.

2. A operação remove permite destruir uma instância de um componente. Esta instância é iden- tificada pela chave primária que é passada como parâmetro da operação. A operação remove possui a seguinte definição em UML:

remove(key : string) : void

Esta operação lança as exceções: InvalidKey, caso a chave primária passada como parâmetro da operação seja inválida e UnknownKeyValue, a chave caso não exista.

3. A operação find_by_primary_key retorna a referência base (interface equivalente) da instância do componente identificada pela chave primária que é passada como parâmetro da operação. A operação find_by_primary_key possui a seguinte definição em UML:

find_by_primary_key(key : string) : ObjRef

Esta operação lança as exceções: InvalidKey, caso a chave primária passada como parâmetro da operação seja inválida e UnknownKeyValue, caso não exista uma instância de componente associada a chave fornecida.

4. A operação get_primary_key retorna o valor da chave primária associada com a instância de um componente. A operação get_primary_key possui a seguinte definição em UML:

get_primary_key(comp : ObjRef) : String

Esta operação não lança nenhuma exceção.

Modelo de Projeto para Fábrica de Elementos

A fábrica de elementos consiste de um objeto que expõe a operação create. Esta operação permite criar instâncias de cada um dos elementos especificados por um componente CM-tel. A operação recebe como parâmetro a referência da interface equivalente do componente e retorna a referência do elemento criado. A operação create possui a seguinte definição em UML:

create(inteq: ObjRef) : ObjRef

A operação create não lança nenhuma exceção.

Modelo de Projeto para Portas Operacionais

O modelo de projeto para as portas operacionais tipo faceta é apresentado na Figura 3.23. As operações definidas na faceta são dependentes da lógica da aplicação e devem ser realizadas na classe que implementa a faceta (FacetImpl).

instantiates FacetFactory

+create()

FacetImpl <<facet>>

Fig. 3.23: Projeto do elemento faceta.

Quanto aos receptáculos, as suas operações são realizadas na interface equivalente do componente conforme ilustra a Figura 3.24. O primeiro parâmetro destas operações identifica o receptáculo para o qual a operação é direcionada.

1. Para receptáculos simples, as operações connect, disconnect e get_connection possuem a seguinte definição em UML (ObjRef denota uma referência de uma interface remota):

connect(rec : Receptacle, peer : ObjRef) : void disconnect(rec : Receptacle) : void

get_connection(rec : Receptacle) : ObjRef

A operação connect lança a exceção AlreadyConnected, caso o receptáculo já esteja conectado a uma interface remota no momento da operação. As operações disconnect e get_connection lançam a exceção NoConnection, caso o receptáculo não esteja conectado no momento da ope- ração. <<receptacle>> +multiple = false <<receptacle>> +multiple = true +connect() +disconnect() +get_connection() +subscribe() +unsubscribe() +get_connections() ComponentImpl ComponentImpl

2. Para receptáculos múltiplos as operações subscribe, unsubscribe e get_connections possuem a seguinte definição em UML:

subscribe(rec : Receptacle, peer : ObjRef) : Cookie unsubscribe(rec : Receptacle, conn : Cookie) : void get_connections(rec : Receptacle) : Cookie[]

A operação subscribe retorna um identificador de conexão (cookie), que é utilizado na operação

unsubscribe para identificar a conexão a ser desfeita.

A operação subscribe lança a exceção AlreadyConnected, caso o receptáculo já esteja conec- tado à referência passada como parâmetro da operação. A operação unsubscribe lança a ex- ceção InvalidConnection, caso o identificador de conexão não corresponda a uma conexão existente no momento da operação. A operação get_connections não lança nenhuma exceção.

Modelo de Projeto para Portas de Sinal

O modelo de projeto para as portas de sinal é apresentado na Figura 3.25. As classes EmitterImpl e PublisherImpl implementam as portas emissoras e publicadoras de eventos. O evento é propagado por estas classes para todas as portas consumidoras conectadas. A classe ConsumerImpl implementa a porta consumidora de eventos.

+addActionListener() 1..n instantiates EmitterFactory +create() instantiates PublisherFactory +actionPerformed() +create() ConsumerFactory instantiates +create() notify EventProducer +actionPerformed() EventListener +connect() EmitterImpl <<publisher>> +subscribe() PublisherImpl +removeActionListener() ConsumerImpl +push() <<consumer>> <<emitter>> register register register consumer : Consumer uses uses +actionPerformed() emits emits 1..n 1..n +addActionListener() +removeActionListener() Event Service +disconnect() +unsubscribe()

1. A classe EmitterImpl armazena a referência da porta consumidora conectada passada como parâmetro da operação connect (esta referência é invalidada pela operação disconnect). Eventos gerados pela aplicação são propagados pela própria classe EmitterImpl, por meio da invocação da operação push disponibilizada na porta consumidora.

As operações connect e disconnect possuem a seguinte definição em UML:

connect(peer : Consumer) : void disconnect() : void

A operação connect lança a exceção AlreadyConnected caso a porta emissora já esteja conec- tada a um consumidor de eventos no momento da operação. A operação disconnect lança a exceção NoConnection caso a porta emissora não esteja conectada no momento da operação. A sintaxe de pré e pós-condições em OCL para estas operações é dada abaixo:

context EmitterImpl::connect(peer : Consumer) pre: peer <> ’null’ and self.consumer = ’null’ post: self.consumer = peer

context EmitterImpl::disconnect() pre: self.consumer <> ’null’ post: self.consumer = ’null’

2. No caso de portas publicadoras de eventos a propagação ocorre por um serviço de eventos que opera no estilo push. Este serviço deve prover interfaces de gerenciamento para registro de produtores e consumidores de eventos e para submissão de eventos para distribuição. A ope- ração subscribe disponibilizada pela porta publicadora registra a porta consumidora passada como argumento no serviço de eventos e retorna um identificador da conexão (cookie). A opera- ção unsubscribe recebe como parâmetro um identificador de conexão e desregistra a respectiva porta consumidora. Eventos gerados pela aplicação são submetidos ao serviço de eventos para difusão, através da interface de difusão do serviço, para todas as portas conectadas .

As operações subscribe e unsubscribe possuem a seguinte definição em UML:

subscribe(peer : Consumer) : Cookie unsubscribe(conn : Cookie) : void

A operação subscribe lança a exceção AlreadyConnected caso a porta emissora já esteja conec- tada ao consumidor de eventos passado como parâmetro da operação. A operação unsubscribe lança a exceção InvalidConnection caso o identificador de conexão não corresponda a uma conexão existente no momento da operação.

3. As portas consumidoras de eventos recebem eventos a partir de um serviço de eventos que opera no estilo push. A interface Consumer define a operação push. A implementação desta operação recebe eventos gerados pelas portas produtoras de eventos conectadas.

A operação push possui a seguinte definição em UML:

push(evt : Event) : void

A operação lança a exceção Disconnected caso a porta consumidora esteja desconectada no momento da operação.

Modelo de Projeto para Portas Stream

O modelo de projeto para as portas de fluxo contínuo (stream) é apresentado na Figura 3.26.

uses uses uses instantiates +create() TransmitterFactory TransmitterImpl instantiates +create() BroadcasterImpl BroadcasterFactory instantiates +create() PlayerFactory PlayerImpl player : Player <<broadcaster>> <<transmitter>> <<player>> +disconnect() +start() +stop() +connect() +subscribe() +unsubscribe() +start() +stop() +start() +stop() Streamming Service

Fig. 3.26: Projeto dos elementos de fluxo contínuo.

As classes TransmitterImpl, BroadcasterImpl e PlayerImpl implementam as portas transmissoras, difusoras e apresentadoras de fluxo contínuo, respectivamente. Estas classes utilizam um serviço de controle e gerência dos fluxos de áudio e vídeo.

1. As operações connect e disconnect do elemento Transmitter possuem a seguinte definição em UML:

connect(peer : Player) : void disconnect() : void

A operação connect lança a exceção AlreadyConnected, caso a porta transmissora já esteja conectada a um apresentador de mídia no momento da operação. A operação disconnect lança a exceção NoConnection, caso a porta emissora não esteja conectada no momento da operação.

2. As operações subscribe e unsubscribe do elemento Broadcaster possuem a seguinte definição em UML:

subscribe(peer : Player) : Cookie unsubscribe(conn : Cookie) : void

A operação subscribe lança a exceção AlreadyConnected caso a porta difusora já esteja conec- tada ao apresentador de mídia passado como parâmetro da operação. A operação unsubscribe lança a exceção InvalidConnection caso o identificador de conexão não corresponda a uma conexão existente no momento da operação.

3. As operações de controle de fluxos multimídia: start e stop presentes em todos os elementos de fluxo contínuo possuem a seguinte definição em UML:

start() : void stop() : void

Estas operações não lançam exceções.

Modelo de Projeto para Elementos de Configuração

O modelo de projeto para as portas de configuração é apresentado na Figura 3.27.

A classe PropertySetImpl implementa a interface do elemento de configuração. Esta classe uti- liza um serviço de propriedades (PropertyService) para a manipulação remota das propriedades de um componente por meio de duas operações. A operação set permite criar e alterar propriedades, enquanto a operação get permite acessar propriedades. Estas operações são definidas em UML como:

set(prop : Property) : void get(name : string) : Property

As operações lançam a exceção PropertyException em caso de falha na criação ou alteração da propriedade (por exemplo, alterar o valor de uma propriedade invariante), ou em caso de acesso a uma propriedade inexistente (operação get).

A operação interna getProperty obtém uma propriedade específica de um componente. A opera- ção create da fábrica PropertySetFactory permite criar um elemento de configuração vazio ou com um conjunto inicial de propriedades.

0..n instantiates +create() PropertySetImpl PropertySetFactory uses Property <<propertyset>> +get() +set() +getProperty() Simple +value : unspecified 1..n Struct 1..n Sequence +type : string +rights[0..1] : string Property Service

Fig. 3.27: Projeto do elemento de configuração.