Os elementos do metaesquema são classes, propriedades e métodos. O metaesquema também suporta indicações e associações como tipos de classes e referências como tipos de propriedades.
As classes podem ser organizadas em uma hierarquia de generalização que representa relações de subtipo entre as classes. A hierarquia de generalização é um gráfico direcionado com raiz que não suporta várias heranças.
Uma classe regular pode conter propriedades escalares ou de matriz de qualquer tipo intrínseco, como booleano, inteiro, string e outros. Ela não pode conter classes embutidas ou referências a outras classes.
Uma associação é uma classe especial que contém duas ou mais referências. Ela representa uma relação entre dois ou mais objetos. Devido à forma como as associações são definidas, é possível estabelecer uma relação entre classes sem afetar nenhuma das classes relacionadas. Isto é, a adição de uma associação não afeta a interface das classes relacionadas. Somente associações podem ter referências.
O fragmento do esquema na ilustração a seguir mostra as relações entre alguns objetos CIM que o ZfD usa.
A ilustração mostra como o esquema CIM é mapeado para um esquema DBMS relacional. As classes são mostradas com o nome da classe como o título da caixa. As associações são etiquetadas dentro das linhas entre duas classes.
A hierarquia de herança deste fragmento de esquema é mostrada na ilustração a seguir do esquema CIM 2.2. As referências mostradas como tipo Ref estão em negrito com cada subtipo de associação especificando o tipo da referência.
CIM é um modelo de objeto completo com classes, herança e polimorfismo. O mapeamento gerado para um esquema relacional preserva esses recursos ao máximo. Os dois aspectos a seguir são parte do mapeamento relacional:
Esquema lógico: O esquema lógico define como os dados aparecem para os aplicativos, de forma semelhante a uma API. O objetivo é que o esquema lógico permaneça o mesmo, independente do banco de dados subjacente, de forma que o aplicativo possa ser executado sem modificações em qualquer banco de dados suportado. Apesar de SQL (pronuncia-se ‘síquel’) ser um padrão, esse objetivo não é totalmente possível. O aplicativo precisará saber mais sobre o banco de dados em uso e essas informações poderão ser abstraídas e isoladas em uma área pequena do código do aplicativo.
Esquema físico: O esquema físico define como os dados são estruturados no banco de dados. O esquema tende a ser específico para o banco de dados, devido à natureza do SQL e do RDBMS. Este documento descreverá o esquema físico apenas em termos gerais.
Uma tabela no banco de dados representa cada classe na hierarquia CIM. Uma coluna do tipo apropriado na tabela representa cada propriedade não herdada na classe. Cada tabela também possui uma tecla primária, id$, que é um inteiro de 64 bits que identifica uma instância de forma exclusiva. Uma instância de uma classe CIM é representada por uma linha em cada tabela que corresponde a uma classe em sua hierarquia de herança. Cada linha possui o mesmo valor para id$.
Cada classe CIM também é representada por uma visualização que usa id$ para juntar linhas das várias tabelas na hierarquia de herança e gerar um conjunto composto de propriedades (herdadas mais locais) para uma instância dessa classe. A visualização também contém uma coluna extra, class$, do tipo inteiro que representa o tipo da classe (a “mais” folha) real da instância.
Associações são mapeadas da mesma forma que as classes regulares, com uma propriedade de referência representada por uma coluna com o campo id$ da instância de objeto referida. Assim, as associações podem ser percorridas através de uma junção entre o campo de referência na associação e o campo id$ na tabela referida.
A ilustração a seguir descreve uma consulta típica usando esse mapeamento.
Essa consulta encontra todos os computadores anexados a um segmento de rede específico. As classes e relacionamentos envolvidos são destacados com bordas.
Os tópicos a seguir descrevem os dois tipos de esquema:
O esquema lógico é o esquema do banco de dados conforme visto pelos usuários do banco de dados e do aplicativo. O esquema consiste em procedimentos e visualizações armazenados. As tabelas subjacentes não são visíveis ao aplicativo.
Geralmente, cada classe CIM possui o seguinte:
Os componentes do ZfD Inventory usam JDBC* para emitir instruções SQL para o RDBMS e para fazer a conversão entre tipos de dados RDBMS e tipos de dados Java*. O uso de JDBC com procedimentos e visualizações armazenados fornece um nível de abstração que isola o código do aplicativo da tecnologia do banco de dados subjacente e de mudanças no esquema físico.
Os vários elementos do esquema lógico são discutidos mais detalhadamente nas seções a seguir:
Recomendamos que você use os nomes CIM não modificados no esquema do banco de dados. Alguns problemas talvez ainda permaneçam devido às diferenças na nomeação dos esquemas, tais como as seguintes:
A maioria desses problemas são evitados durante a geração de esquemas, preservando as maiúsculas/minúsculas de nomes CIM, abreviando quaisquer nomes que tenham mais de 30 caracteres e colocando aspas duplas em torno de qualquer nome que esteja nos conjuntos de palavras reservadas.
Qualquer nome que tenha mais de 28 caracteres será abreviado para um nome raiz de 28 ou menos caracteres, para que possa ter um prefixo de dois caracteres. Assim, todos os elementos do esquema SQL associados poderão usar o mesmo nome raiz. O algoritmo de abreviação reduz um nome, de forma que se torne mnemônico, reconhecível e, também, exclusivo em seu escopo. O nome abreviado recebe um caractere # como sufixo (observe que # é um caractere ilegal no CIM) para evitar conflito com outros nomes. Se dois ou mais nomes dentro do mesmo escopo gerarem a mesma abreviação, um dígito adicional será anexado para torná-lo exclusivo. Por exemplo, AttributeCachingForRegularFilesMin é abreviado para AttCacForRegularFilesMin#.
Todos esses nomes abreviados são gravados na tabela de nomes abreviados, para que o programa possa procurar o nome CIM real e recuperar o nome abreviado para ser usado com o SQL.
Visualizações são os elementos de esquema mais freqüentemente manipulados pelas consultas e pelo código do aplicativo. Elas usam o mesmo nome que a classe CIM que representam. Por exemplo, a classe CIM_UnitaryComputerSystem é representada por uma visualização chamada CIM.UnitaryComputerSystem.
Quando necessário, os nomes de índices e tabelas auxiliares são criados através da concatenação do nome da classe e da propriedade separados pelo caractere $. Esses nomes costumam ser abreviados. Por exemplo, NetworkAdapter$NetworkAddresses é abreviado para NetAdapter$NetAddresses#. Isso não prejudica de forma alguma os usuários do esquema do ZfD.
No SQL, um usuário com o mesmo nome que o esquema é o proprietário de cada esquema, por exemplo, CIM, ManageWise®, ZENworks® e outros.
Além disso, há um usuário MW_DBA que possui privilégios e direitos do Administrador do Banco de Dados para todos os objetos esquema. A função MW_Reader possui acesso apenas leitura a todos os objetos esquema e a função MW_Updater possui acesso leitura-gravação-execução a todos os objetos esquema.
Aplicativos devem acessar o banco de dados como MW_Reader ou MW_Updater para um banco de dados Sybase, MWO_Reader ou MWO_Updater para um banco de dados Oracle e MWM_Reader ou MWM_Updater para um banco de dados MS SQL Server 2000, dependendo de seus requisitos.
Tipos de dados CIM são mapeados para os tipos de dados mais apropriados fornecidos pelo banco de dados. Normalmente, o aplicativo Java não exige o tipo porque ele usa o JDBC para acessar os dados.
Java não suporta originalmente tipos não assinados; portanto, você deve usar classes ou tipos inteiros do próximo tamanho para representá-los. Da mesma forma, verifique se há problemas durante a leitura ou gravação no banco de dados. Por exemplo, a leitura ou gravação de um número negativo em um campo não assinado no banco de dados provavelmente causará erro.
Strings no CIM e no Java são Unicode*; portanto, o banco de dados é criado usando o conjunto de caracteres UTF8. A internacionalização não apresenta nenhum problema, entretanto, ela pode causar problemas na distinção entre maiúsculas e minúsculas em consultas.
Todos os bancos de dados preservam as maiúsculas/minúsculas de dados de string armazenados dentro deles, mas podem acessar os dados com distinção entre maiúsculas e minúsculas ou durante as consultas. No ZfD, os componentes Consulta de Inventário e Exportação de Dados não são afetados, pois os dados consultados são recuperados do banco de dados antes de serem consultados. Assim, a distinção entre maiúsculas e minúsculas é automaticamente ativada.
No CIM, as strings podem ser especificadas com ou sem um tamanho máximo em caracteres. Muitas strings não possuem tamanho especificado, o que significa que podem ter um tamanho ilimitado. Por questões de eficiência, essas strings ilimitadas são mapeadas para uma string disponível com um tamanho máximo de 254 caracteres. As strings CIM com tamanho máximo são mapeadas para strings do banco de dados variáveis do mesmo tamanho. O tamanho no banco de dados é em bytes e não em caracteres, pois um caractere unicode pode requisitar mais de um byte para armazenamento.
Cada classe CIM é representada no banco de dados por uma visualização que contém todas as propriedades não-matriciais herdadas e locais dessa classe. A visualização tem o mesmo nome da classe CIM. Por exemplo, CIM_System da classe CIM representa uma visualização SQL chamada CIM.System, como mostrado na ilustração a seguir.
A visualização CIM.System é criada com atributos selecionados de várias tabelas. Esses atributos incluem: id$ selecionado de cim.t$ManagedSystemElement,class$ é preenchido automaticamente usando a função mw_dba.extractClass, Caption selecionado de cim.t$ManagedSystemElement, Description selecionado de cim.t$ManagedSystemElement, InstallDate selecionado de cim.t$ManagedSystemElement, Status selecionado de cim.t$ManagedSystemElement, CreationClassName selecionado de cim.t$System, Name selecionado de cim.t$ManagedSystemElement. NameFormat selecionado de cim.t$System.NameFormat, PrimaryOwnerContact selecionado de cim.t$System e PrimaryOwnerName selecionado de cim.t$System. A visualização é criada através da junção das tabelas CIM.t$ManagedSystemElement e CIM.t$System, onde id$ é o mesmo nas duas tabelas.
A visualização CIM.SYSTEM é a seguinte:
CREATE VIEW CIM.System
{
id$,
class$,
Caption,
Description,
InstallDate,
Status,
CreationClassName,
Name,
NameFormat,
PrimaryOwnwerContact,
PrimaryOwnerName
}
AS SELECT
CIM.t$ManagedSystemElement.id$
MW_DBA.extractClass(CIM.t$ManagedSystemElement.id$),
CIM.t$ManagedSystemElement.Caption,
CIM.t$ManagedSystemElement.Description,
CIM.t$ManagedSystemElement.InstallDate,
CIM.t$ManagedSystemElement.Status,
CIM.t$System.CreationClassName,
CIM.t$ManagedSystemElement.Name,
CIM.t$System.NameFormat,
CIM.t$System.PrimaryOwnerContact,
CIM.t$System.PrimaryOwnerName
FROM
CIM.t$ManagedSystemElement,
CIM.t$System
WHERE
CIM.t$ManagedSystemElement.id$ = CIM.t$System.id$
Além das propriedades da classe, a visualização possui os dois campos adicionais a seguir:
Id$: Um identificador de objeto que identifica a instância específica da classe de forma exclusiva. Consulte Identificador de objeto Id$ .
Class$: Um campo de inteiros que identifica o tipo real da classe. Por exemplo, o tipo real de um CIM_System pode ser qualquer uma das subclasses concretas de CIM_System.
Você pode consultar as visualizações usando a instrução SELECT e atualizá-las usando a instrução UPDATE. Como as visualizações não podem ser usadas com as instruções INSERT e DELETE, use os procedimentos construtor e destruidor.
Id$ é um identificador de objeto de 64 bits que identifica uma instância específica de classe de forma exclusiva. Por exemplo, uma instância da classe CIM_Processor. Esse identificador de objeto costuma ser usado como handle opaco de uma instância específica. Id$ é modelado como um número assinado para facilitar a manipulação em Java como tipo de dado longo.
Id$ contém as três partes de informações a seguir e cada uma pode ser extraída chamando o procedimento armazenado apropriado.
Esse campo pode ser extraído usando a função MW_DBA.extractClass(). Esse campo é usado para decisões de tipo ou para acessar informações adicionais sobre a classe da tabela MW_DBA.Class.
O ID do site identifica de forma exclusiva o banco de dados em um site específico. Esse campo torna o identificador de objeto único entre 256 sites, de forma que os dados de inventário de vários sites podem sofrer roll-up para um único banco de dados (Servidor Raiz com Banco de Dados) para efetuar consultas e relatórios sem causar conflitos entre as teclas. O ID do site pode ser extraído usando a função MW_DBA.extractSite().
Essa parte pode ser extraída usando a função MW_DBA.extractId(). Isso não é útil sob o ponto de vista de um usuário final.
O campo id$ é usado em sua totalidade como um handle opaco para uma instância de uma classe. Quando uma classe de associação representa um relacionamento entre instâncias de duas classes, os campos de referência da associação mantêm o id$ das instâncias referenciadas (como os apontadores). Portanto, id$ e esses campos de referência costumam ser usados em condições de associação, durante a construção de consultas do banco de dados que fazem referência a mais de uma visualização.
Cada classe CIM (não-abstrata) concreta possui um procedimento armazenado construtor que deve ser chamado para criar uma instância da classe. Esse procedimento armazenado possui parâmetros de entrada que permitem ao usuário especificar um valor para cada propriedade na classe e um único parâmetro de saída que retorna o id$ alocado para a instância criada. O aplicativo usa esse valor de id$ retornado para construir classes de associação que fazem referência a essa instância específica.
O construtor é nomeado usando o prefixo c$ no nome raiz e cada parâmetro é nomeado usando o prefixo p$ no nome de propriedade raiz. Por exemplo, o construtor de CIM_UnitaryComputerSystem, uma subclasse de CIM_System, é nomeado CIM.c$UnitaryComputerSystem e é construído para Oracle, como mostrado no exemplo a seguir:
CREATE PROCEDURE CIM.c$UnitaryComputerSystem
(
p$id$ OUT NUMBER,
p$Caption IN CIM.t$ManagedSystemElement.Caption%TYPE DEFAULT NULL,
p$Description IN CIM.t$ManagedSystemDescription%TYPE DEFAULT NULL,
p$InstallDate IN CIM.t$ManagedSystemElement.InstallDate%TYPE DEFAULT NULL,
p$Status IN CIM.t$ManagedSystemElement.Status%TYPE DEFAULT NULL,
p$CreationClassName IN CIM.t$System.CreationClassName%TYPE DEFAULT NULL,
p$Name IN CIM.t$ManagedSystemElement.Name%TYPE DEFAULT NULL,
p$PrimaryOwnerContact IN CIM.t$System.PrimaryOwnerContact%TYPE DEFAULT NULL,
p$PrimaryOwnerName IN CIM.t$System.PrimaryOwnerName%TYPE DEFAULT NULL,
p$NameFormat IN CIM.t$System.NameFormat%TYPE DEFAULT NULL,
p$LastLoadInfo IN CIM.t$UnitaryComputerSystem.LastLoadInfo%TYPE DEFAULT NULL,
p$ResetCapability IN CIM.t$UnitaryComputerSystem.ResetCapability%TYPE DEFAULT NULL,
p$PowerManagementSupported IN CIM.t$UnitaryComputerSystem.PowerManagementSupported%TYPE DEFAULT NULL,
p$PowerState IN CIM.t$UnitaryComputerSystem.PowerState%TYPE DEFAULT NULL
)IS
temp NUMBER;
BEGIN
LOOP
SELECT CIM.s$UnitaryComputerSystem.NEXTVAL INTO temp FROM DUAL;
SELECT MW_DBA.makeId(240, temp) INTO temp FROM DUAL;
EXIT WHEN MOD(temp,100) != 0;
END LOOP;
p$id$ := temp;
INSERT INTO CIM.t$ManagedSystemElement (id$, classOid$, Caption, Description, InstallDate, Status, Name)VALUES(p$id$, HEXTORAW('0302100203'), p$Caption, p$Description, p$InstallDate, p$Status, p$Name);
INSERT INTO CIM.t$System (id$, CreationClassName, PrimaryOwnerContact, PrimaryOwnerName, NameFormat)VALUES(p$id$, p$CreationClassName, p$PrimaryOwnerContact, p$PrimaryOwnerName, p$NameFormat);
INSERT INTO CIM.t$UnitaryComputerSystem (id$, LastLoadInfo, ResetCapability, PowerManagementSupported, PowerState) VALUES(p$id$, p$LastLoadInfo, p$ResetCapability, p$PowerManagementSupported, p$PowerState);
END;
Procedimentos armazenados podem ser chamados com argumentos de posição, argumentos de palavra-chave ou com uma combinação de ambos. Se algum argumento de posição for fornecido, ele deverá preceder qualquer argumento de palavra-chave. Sempre use argumentos de palavra-chave quando chamar procedimentos armazenados construtores. Isso fornece um isolamento melhor das mudanças do esquema CIM, que causam a inserção de parâmetros extras ou o registro de parâmetros existentes; qualquer um dos dois pode interromper uma chamada posicional de uma forma provavelmente não detectável. Os procedimentos são gerados de forma que nenhum parâmetro omitido terá padrão NULL.
É permitido usar a notação posicional para o primeiro parâmetro p$id$, que é o parâmetro de saída que retorna o identificador de objeto da nova instância criada.
A seguinte amostra de código JDBC mostra como chamar um procedimento armazenado usando notação posicional para o primeiro argumento e notação de palavra-chave para todos os argumentos subseqüentes no Sybase.
CallableStatement CS =
conn.prepareCall( "{call CIM.c$UnitaryComputerSystem( ?, p$Name=?, p$Description=?)}" )
cs.registerOutParameter ( 1, java.sql.Types.BIGINT ); //id$
cs.setString( 2, "Bogus_UCS_1") ; //Name
cs.setString( 3, "Created with mixture of positional & keyword args" ); // Description
cs.executeUpdate();
long id = cs.getLong ( 1 );
SQLWarning w = cs.getWarnings();
if( w != null )
printWarnings( w );
else
System.out.println("Created UCS id$ = " + id );
A sintaxe para a notação de palavra-chave difere no Sybase ASA, MS SQL 2000 e Oracle. No Sybase ASA e no MS SQL 2000, a sintaxe é KEYWORD=valor. No Oracle, a sintaxe é KEYWORD => valor. Um código corretamente gravado construirá dinamicamente a string de chamada usando sintaxe apropriada para o banco de dados em uso.
Cada classe CIM não-abstrata possui um procedimento armazenado destruidor que é chamado para destruir uma instância da classe. Esse procedimento armazenado possui somente um parâmetro de entrada que especifica o identificador de objeto (id$) da instância a ser destruída e não retorna valor algum.
O destruidor apaga as linhas apropriadas em todas as tabelas relevantes, incluindo as linhas da cadeia de herança e quaisquer associações que façam referência à instância sendo destruída. Somente a associação é destruída, os objetos associados não são destruídos. Se houver necessidade de destruir a associação, os programadores deverão garantir que eles não sejam destruídos. O destruidor é nomeado usando o prefixo d$ no nome raiz e o parâmetro do identificador de objeto único é nomeado p$id$. Esse procedimento é chamado usando notação posicional. Por exemplo, o destruidor para CIM_UnitaryComputerSystem, uma subclasse concreta de CIM_System, é nomeado CIM.d$UnitaryComputerSystem.
O esquema físico inclui elementos necessários para implementar o banco de dados. O esquema físico difere em cada banco de dados. Um esquema físico típico consiste em:
O esquema lógico é colocado em camadas sobre o esquema físico, tornando desnecessário para usuários e aplicativos conhecerem o esquema físico.