MetaObject

De BIS Wiki
Ir para navegação Ir para pesquisar

Meta Object é o Objeto do Objeto! Mais fácil que isso só dois disso!!! Se não entendeu continue lendo...

A definição da 'Meta Dados' é "A informação da Informação". Por exemplo, se você tem a informação do tipo texto "Eu amo o BIS". Essa informação contém outras informações, como "tamanho", "charset", "língua", etc.. Essas informações (dados) da própria informação são chamadas de 'Meta Dados'.

De forma similar o BIS tem seus 'Meta Objects', que tem a finalidade de descrever seus próprios objetos. No caso, são utilizados para descrever cada um dos BISVO do sistema.


O Problema

Em várias partes do BIS Framework há processos automatizados com métodos que tratam as classes BISVO (ou suas herdeiras), no entanto sua implementação não conhece especificamente cada objeto. É possível orientá-lo a obter o atributo correto a partir de uma String de parâmetros.

Por exemplo, imagine que estamos montando um relatório de clientes. Os dados seriam uma coleção de PersonVO. Para montar o relatório queremos que o Framework crie uma coluna com o atributo "fullName". E que dentro de PersonVO, temos a referência para outro PersonVO que indica seu pai, no atributo "dad". E queremos outra coluna com o nome completo do pai.

Ao passar os caminhos para o framework por String seriam "fullName" e "dad.fullName".

O problema de passar por String é que se o atributo deixar de existir ou qualquer alteração/refactory que mude o atributo, ou ainda qualquer tipo de erro de digitação, fará com que o código compile normalmente mas não funcione. E mesmo que ele seja testado na hora, alterações futuras podem fazer com que o código deixe de funcionar em outras partes do sistema. Tupo por não haver validação dos atributos dentro da String.


Para resolver isso existe o MetaObject. O Meta object é um objeto espelho do VO, que descreve o VO e seus métodos e atributos. De forma que ele monta a String a ser passada somente durante o RunTime. Durante o tempo de compilação ele mantém métodos que deixam de existir caso o atributo deixe de existir. O que fará com que o código "quebre" já com erros de compilação.

Funcionamento

O MetaObject por padrão tem o mesmo nome que o VO a qual ele descreve e é salvo no mesmo package, com a única diferença que leva um sufixo '_'. Ou seja, caso tenhamos um PersonVO no sistema, o seu MetaObject seria o PersonVO_, salvos um "do lado do outro".

Este objeto tem métodos co o exato nome do atributo do VO que ele representa. Por exemplo, se o PersonVO tem um atributo 'fullName', o PersonVO_ terá um método 'fullName()', que retornará a String 'fullName' como desejado para passar para o Framework.

Nos casos em que o atributo retorne outro VO, como no nosso exemplo do PersonVO com o atributo 'dad' que retorna outro PersonVO, o PersonVO_ terá um método chamado 'dad()', que dessa vez não retorna uma String, mas sim o MetaObject do objeto retornado no VO. No nosso caso o próprio PersonVO_. E então conseguiríamos obter o caminho para o atributo 'fullname' do objeto retornado a partir do retorno de 'dad'. O código ficaria assim:

dad().fullName()

O que retornaria a String "dad.fullName", como esperado pelo Framework. E com a vantagem que esse código "quebra" se dad ou fullname deixarem de existir em PersonVO.


Imagine agora que você queira o caminho de 'dad' e não de um atributo dentro de dad. E dad não retorna a String, retorna outro MetaObject de PersonVO. Nestes casos, pode-se chamar o método path(). Que força o retorno do caminho até aquele ponto, sem obter um atributo dentro do MetaObject retornado. Por exemplo:

dad().path()

Essa código retornará a String "dad".


A partir deste funcionamento podemos obter e descrever o caminho para qualquer propriedade de um VO independente de quantas referências ou "níveis de cadeia" um VO tenha dentro do outro.

Constantes Vs. Métodos

Para evitar que o MetaObject seja instanciado o tempo todo, cada Meta Object tem uma contante chamada "VO" que carrega uma instância estática do objeto. A maneira correta de utilizar o MetaObject seria a seguinte (de acordo com o exemplo de PersonVO citado acima):

Java 256.png Utilização do MetaObject por Métodos
PersonVO_.VO.fullName() //Retorna a String "fullName"
PersonVO_.VO.dad().path() //Retorna a String "dad"
PersonVO_.VO.dad().fullName() //Retorna a String "dad.fullName"

A sintaxe citada acima é que é definida por métodos. É a melhor e mais simples maneira de se referenciar os atributos ou suas cadeiras de atributos.


Porém, há ainda as constantes de atributos. As constantes sequem a seguinte sintaxe:

Java 256.png Utilização do MetaObject por Constantes
PersonVO_._fullName //Constante com a String "fullName"
PersonVO_._dad //Retorna a String "dad"

Para um atributo direto do VO (que não retorne outro VO), não há diferença entre um método e outro. Isto é "PersonVO_.VO.fullName()" ou "PersonVO_._fullName" tem exatamente o mesmo resultado. Mas note que nessa sintaxe a constante '_dad' retorna diretamente a String "dad" ao invés do MetaObject do objeto retornado pelo atributo 'dad' original do VO. Isso impossibilita que seja montada uma cadeia completa com atributos aninhados!


Se o acesso por constantes tem menos funcionalidades, para que existem ambos? Em alguns casos a referência ao atributo precisa ser uma constante final. Como por exemplo a referência de atributos dentro de Annotations. Nestes casos a utilização do método não pode ser utilizado, pois o java entende que o retorno de um método não será constante.

Mas e se na annotation eu precisar referenciar um atributo aninhado? Como obter o caminho completo? A resposta é que não tem como obter diretamente. Mas mesmo assim recomendamos a utilização dos MetaObjects. Por exemplo para obter o mesmo resultado de "PersonVO_.VO.dad().fullName()" (que seria "dad.fullName") teriamos de utilizar o seguinte código:

Java 256.png Utilização do MetaObject por Constantes
PersonVO_._dad + "." + PersonVO_._fullName


Desta forma temos o mesmo resultado utilizando apenas os acessos de constantes. Embora mais trabalhoso, e ainda passível de se montar um caminho de atributos inválidos, o código continuará "quebrando" caso alguma das propriedades mude ou deixe de existir. Melhorando a qualidade do código evitando BUGs e erros.

Escrevendo o MetaObject

Bom, tudo isso é legal, mas é muito trabalhoso ter que ficar escrevendo e editando o MetaObject a cada vez que faço uma alteração no VO.

FATO! Por isso o BIS conta com um Plugin para Eclipse que sempre que vc escrever uma clase cujo nome termine com VO e que estenda BISVO, ele gera automaticamente a classe do lado do VO.

Para instalar e fazer o BISMetaObjectGenerator verifique a página de instalação do ambiente do BIS: Preparação dos Ambientes.