UNIVERSIDADE FEDERAL DE SANTA CATARINA Geração de Informações de Mapeamento no Sistema de Integração de Esquemas XML BInXS Eduardo Vaz de Mello Traballi Bozzi Florianópolis – SC 2009 2 UNIVERSIDADE FEDERAL DE SANTA CATARINA DEPARTAMENTO DE INFORMÁTICA E ESTATÍSTICA CURSO DE SISTEMAS DE INFORMAÇÃO Geração de Informações de Mapeamento no Sistema de Integração de Esquemas XML BInXS Eduardo Vaz de Mello Traballi Bozzi Trabalho de conclusão de curso apresentado como parte de requisitos para obtenção do grau de Bacharel em Sistemas de Informação. Florianópolis – SC 2009 3 Eduardo Vaz de Mello Traballi Bozzi Geração de Informações de Mapeamento no Sistema de Integração de Esquemas XML BInXS Trabalho de conclusão de curso apresentado como parte de requisitos para obtenção do grau de Bacharel em Sistemas de Informação. _______________________________________ Prof. Dr. Ronaldo dos Santos Mello Orientador Banca examinadora: _______________________________________ Prof. Frank Siqueira _______________________________________ Prof. Fernando Ostuni Gauthier 4 LISTA DE ABREVIATURAS API Application Program Interface BInXS Bottom-up Integration of XML Schemata DTD Document Type Definition HTML Hiper Text Transmission Protocol OWL Web Ontology Language RDF Resource Description Framework SGBD Sistema de Gerenciamento de Banco de Dados XML eXtensible Markup Language XSD XML Schema Definition W3C World Wide Web Consortium MVC Model View Control SAX Simple API for XML ORM Object-relational mapping XPATH XML Path Language 5 LISTA DE FIGURAS Figura 1: Exemplo documento XML – exemplo.xml Figura 2: Grafo de uma estrutura de um esquema XML Figura 3: Trecho de um documento XSD. Figura 4: Exemplo de classes na OWL Figura 5: Exemplo de propriedade OWL Figura 6: Exemplo de um documento OWL. Figura 7: Exemplos de Consultas XPath Figura 8: Representação gráfica de uma modelagem ORM detalhando objetos léxicos (objetos tracejados) e não-léxicos (objetos contínuos). Figura 9: Etapas do BInXS. Figura 10: Esquema Conceitual e XSDs (MELLO, 2000) Figura 11: Arquitetura da Etapa de Conversão do BInXS Figura 12: Fases de atuação do módulo de mapeamento. Figura 13: Trecho de uma XSD Figura 14: Sintaxe do mapeamento para elemento e atributo. Figura 15: Mapeamento dos elementos Livro e Endereço Figura 16: Mapeamento elemento nomeado com repetição Figura 17: Mapeamento do conceito end_page e do relacionamento de elemento componente texto () Figura 18: Mapeamento do relacionamento de herança Periódico-Titulo Figura 19: Mapeamento do conceito ProfessorType e do relacionamento de uma qualificação Professor-ProfessorType Figura 20: Mapeamento de relacionamento com um elemento ANY, entre os conceitos Coleção-Disco e Coleção-Video. Figura 21: Estrutura do Modelo MVC (GAR 2005). Figura 22: Trecho do XSD SigmodRecord. Figura 23: Catalogação no pré-processamento. Figura 24: Inclusão de conceitos e relacionamentos na conversão. Figura 25: Documento OWL contendo o mapeamento. 6 SUMARIO LISTA DE ABREVIATURAS ..................................................................................................... 4 LISTA DE FIGURAS ................................................................................................................... 5 1. INTRODUÇÃO .................................................................................................................... 8 2. TECNOLOGIAS UTILIZADAS .......................................................................................... 9 2.1. 2.2. 2.3. 2.4. 2.5. 3. AMBIENTE BInXS ........................................................................................................... 19 3.1. 3.2. 4. XML .............................................................................................................................. 9 XSD (Schemas XML) ................................................................................................. 12 OWL ............................................................................................................................ 14 XPATH ....................................................................................................................... 16 ORM ............................................................................................................................ 17 Visão Geral .................................................................................................................. 19 Etapa de Conversão..................................................................................................... 22 MÓDULO DE GERAÇÃO DE MAPEAMENTOS ........................................................... 24 4.1. 4.2. Estratégia de Mapeamento .......................................................................................... 25 Catálogos de Mapeamento .......................................................................................... 26 4.2.1. Catálogo de Elementos Renomeados ................................................................. 26 4.2.2. Catálogo de Elementos Removidos ..................................................................... 27 4.2.3. Catálogo de Elementos Virtuais .......................................................................... 28 4.3. Mapeamento de Conceitos ......................................................................................... 28 4.3.1. Mapeamento para um Elemento ........................................................................ 28 4.3.2. Mapeamento para um Atributo .......................................................................... 29 4.4. Mapeamento de Relacionamentos ............................................................................. 30 5. 4.4.1. Mapeamento para um Elemento Componente Nomeado ................................. 30 4.4.2. Mapeamento para um Elemento Componente Nomeado com Repetição ........ 32 4.4.3. Mapeamento para um Elemento Componente texto......................................... 33 4.4.4. Mapeamento de Relacionamento de Herança ................................................... 35 4.4.5. Mapeamento de uma Qualificação ..................................................................... 36 4.4.6. Mapeamento para um Relacionamento com Elemento ANY ............................. 37 IMPLEMENTAÇÃO DO MÓDULO DE MAPEAMENTO.............................................. 38 5.1. 5.2. 5.3. 5.4. 6. Tecnologias Utilizadas ................................................................................................ 38 Projeto de Classes........................................................................................................ 39 Arquitetura da Catalogação ......................................................................................... 41 Arquitetura do Mapeamento........................................................................................ 42 ESTUDO DE CASO ........................................................................................................... 43 6.1. 6.2. 6.3. 6.4. Fonte de Dados ............................................................................................................ 43 Pré-Processamento e Catalogação. .............................................................................. 44 Conversão e Geração do Mapeamento. ....................................................................... 45 Reestruturação e Informação de Mapeamento. ........................................................... 46 7 7. CONCLUSÃO .................................................................................................................... 48 7.1. Trabalhos Futuros........................................................................................................ 48 APÊNDICE A – Artigo ............................................................................................................... 50 APÊNDICE B – Código Fonte.................................................................................................... 57 B.1 B.2 B.3 B.4 B.5 B.6 B.7 B.8 B.9 - BEAN ............................................................................................................................ 57 CONTROLE ................................................................................................................... 58 PERSISTÊNCIA .............................................................................................................. 81 DAO ............................................................................................................................. 83 ED ................................................................................................................................ 85 INTERFAC ................................................................................................................... 104 MODELO .................................................................................................................... 109 SUBETAPAS ................................................................................................................ 113 TRATADORES ............................................................................................................. 123 APÊNDICE C – Documento XSD referente a SIGMOD ......................................................... 163 REFERÊNCIAS. ....................................................................................................................... 164 8 1. INTRODUÇÃO Atualmente um dos maiores obstáculos da indústria de software é a interoperabilidade de aplicativos de diferentes plataformas. Podemos destacar ainda a dificuldade da integração de dados de fontes de origens distintas. Este processo ao longo do tempo vai tornando os sistemas mais isolados e distantes entre si, uma vez que não há comunicação entre eles. Outra conseqüência para este fato é o inchaço no volume de dados de cada sistema por causa da replicação de dados. Para facilitar a solução deste problema existe a linguagem XML, que tem como uma das suas principais premissas o transporte de dados semi-estruturados em estruturas bastante flexíveis, facilitando a comunicação entre os sistemas (W3C). Com base na flexibilidade da XML e na necessidade da unificação dos dados neste formato, foi idealizado o sistema BInXS (Mello; Heuser, 2005). BInXS tem como principal função a integração semântica de esquemas XML com o objetivo de definir um esquema global que possa servir de base para a consulta a fontes de dados heterogêneos representados em XML. O processo de integração realizado BInXS é dividido em duas fases principais: conversão e unificação. Durante a primeira fase, esquemas XML das fontes são convertidos para esquemas conceituas, visando facilitar a compreensão do usuário que acessa o esquema global, bem como facilitar uma integração de esquemas em nível semântico. As alterações realizadas nesta fase são passíveis de mapeamento, pois é necessário identificar que elemento ou atributo de um esquema XML local cada conceito no nível conceitual representa. Por exemplo, um conceito chamado Autor no esquema conceitual pode se referir às tags Escritor e Criador em duas fontes de dados XML diferentes. Este trabalho implementa a geração de informações de mapeamento para a fase de conversão do sistema BInXS. O objetivo principal é o desenvolvimento de um módulo que seja capaz de gerar todo o mapeamento necessário, durante o momento que cada esquema XML de entrada para o sistema tem suas estruturas lógicas convertidas para estruturas conceituais. 9 Desta forma, ao final do processo, tem-se o relacionamento de cada conceito do esquema conceitual global com elementos ou atributos dos esquemas XML local. Com a utilização das tecnologias recomendadas pela a W3C como a XML(W3C,a) (transporte de dados), OWL (W3C,b) (especificação de ontologias e esquemas conceituais) e XPath(W3C,c) (linguagem de navegação em documentos XML), este módulo de geração de mapeamento é desenvolvido aplicando-se regras pré-definidas no projeto do sistema BInXS. Estas regras são explicadas a seguir, assim como as tecnologias, que são vistas com um maior detalhamento no capitulo 2. O capítulo 3 dá uma visão geral sobre o sistema BInXS: sua arquitetura e etapas (Conversão e Unificação). Uma ênfase é dada no modelo conceitual canônico, que é o modelo utilizado nesse processo para descrever o esquema conceitual global. O capítulo 4 apresenta as regras utilizadas para o mapeamento dos conceitos do domínio e o capítulo 5 descreve a implementação do módulo de mapeamento, temos a conclusão deste trabalho, com análise de resultados e indicações de trabalhos futuros. 2. TECNOLOGIAS UTILIZADAS Este capítulo aborda as tecnologias adotadas para a formalização da solução apresentada pelo BInXS, visando um melhor entendimento do seu processo. A escolha de algumas dessas tecnologias foram realizadas em trabalhos anteriores a este, que realizaram a implementação de parte do processo de integração. 2.1. XML Atualmente no mundo tecnológico há um obstáculo entre os sistemas de informação no que diz respeito à transferência de dados. Isto se deve 10 principalmente ao fato de ser escritos em linguagens diferentes ou não pertencerem à mesma plataforma operacional ou até mesmo por terem algum problema de compatibilidade para a troca de dados. A XML (eXtensible Markup Language) é uma solução que permite a representação e o intercâmbio de informações entre sistemas, sob uma estrutura de um arquivo auto-descritivo, com grande legibilidade e de fácil entendimento (XML, 2005). A XML é um formato de arquivo que se assemelha muito com a HTML por também ser uma linguagem de marcação, ou seja, definir os dados de seus documentos através de tags. Enquanto a HTML tem suas tags pré-definidas e assim apresenta um esquema de dados fixo, a XML é flexível, permitindo a definição de tags (elementos) que indicam a intenção dos dados em um documento apresentando um esquema semi-estruturado (DOW, 2000). Em outras palavras, podemos dizer que é possível classificar cada elemento de um documento XML, especificando se este representa um elemento numérico ou alfanumérico e ainda especificar heranças, seqüências e cardinalidade. Tudo isto através das informações contidas nas tags que rotulam os elementos. Um arquivo (documento) XML é utilizado tanto para armazenar dados quanto para transportá-los – a HTML por sua vez, é utilizada apenas para formatar a apresentação de dados. A sua flexibilidade na definição de um domínio de dados em um esquema, aplica-se muito bem para a transferência de dados para diversos softwares de diferentes plataformas. A Figura 1 mostra um exemplo de documento XML: 11 Figura 1: Exemplo documento XML – exemplo.xml Na Figura 1 pode-se identificar a tag livraria que logo depois indica a existência de uma tag livro que tem as tags titulo, autor e preço, sendo todas elas auto-descritivas. Uma tag é denominada elemento. Um elemento no documento XML define-se pela a seguinte sintaxe: <livro> </livro>, ou seja, cada elemento terá uma tag inicial (abertura) e uma tag final (fechamento). No exemplo apresentado na Figura 1, na linha 1, tem-se livraria como um elemento raiz, por conter todos os outros elementos e também por seguir a sintaxe da linguagem de marcação. O elemento raiz por sua vez, é um elemento que só ocorre uma vez e contém todos os outros elementos do documento. Cada elemento raiz pode conter outros elementos (filhos) ou valores de dado, sendo que os últimos elementos na hierarquia são denominados folhas. A estrutura de um esquema XML se apresenta em forma de árvore, conforme podemos ver na figura 2. Na estrutura de um documento XML encontramos duas classificações de elementos: simples e complexos. Os elementos simples são aqueles que têm como conteúdos apenas dados em forma de texto. O elemento autor da Figura 2 ilustra um elemento simples dentro dessa estrutura XML. Os elementos complexos são aqueles que contêm abaixo de si um ou mais elementos na estrutura. Estes podem carregar tanto elementos como 12 informação em forma de texto. Um exemplo de atributo complexo pode ser visualizado na Figura 2, no caso, o elemento livro, que possui os elementos <titulo>, <preço> e <autor>. Um elemento pode ter um ou mais atributos, que podem ser ou não obrigatórios. Os atributos qualificam os elementos e assim descrevem informação adicional acerca dos mesmos. Todos os atributos contêm um valor, que deve ser apresentado dentro de apóstrofes e são sensíveis a caracteres maiúsculos e minúsculos. Na Figura 1, na linha 3, podemos observar o atributo category para o elemento livro, onde há o atributo seguido de seu respectivo valor: “INFANTIL”. Para um arquivo XML ser considerado válido, ele deve possuir um esquema associado, que forneça as informações de como os elementos devem estar estruturados. Existem duas recomendações da W3C para a definição de esquemas XML: DTD e XML Schema(W3C,c). Figura 2: Grafo de uma estrutura de um esquema XML. 2.2. XSD (Schemas XML) Os documentos XSDs têm a finalidade de expressar um vocabulário e validar regras utilizadas em um documento XML. Se quisermos validar um 13 documento XML através de um Schema XML este deverá estar bemformatado. A Figura 3 ilustra um trecho de documento XSD e que define as características para o XML correspondente como: SigmodRecord é um elemento raiz, de onde deriva os demais elementos na árvore XML. Verificamos a cardinalidade do elemento issue que possui de zero a infinitas ocorrências no contexto. O XSD classifica cada elemento como simples ou complexo, assim como o tipo de data que corresponde ao elemento. Como exemplo volume é denominado um elemento simples do tipo integer enquanto issue classificado como elemento complexo do tipo IssueType. Figura 3: Trecho de documento XSD. é 14 Para analisar e validar o documento XML com o XSD, estes arquivos são submetidos a um PARSER ou processador XML. Após a análise é gerado um resultado da aplicação das regras inferidas no documento descritor sobre o XML. 2.3. OWL A OWL (Ontology Web Language) é uma linguagem baseada nas linguagens OIL e DAML+OIL, sendo utilizada para definir e instanciar ontologias na Web, sendo também uma recomendação W3C. A OWL foi projetada para facilitar o processamento do conteúdo de informações por máquinas, oferecendo um vocabulário adicional com uma semântica formal. Uma ontologia OWL contém descrições de classes, propriedades e possíveis relacionamentos entre classes. As classes representam entidades do domínio. Todas as classes definidas pelo usuário são subclasses da classe owl:Thing, padrão pré-definido da OWL. A Figura 4 exemplifica três classes da ontologia de domínio “Livro”, tomando por base a Figura 2. <owl:Class rdf:ID=”Titulo”/> <owl:Class rdf:ID=”Preco”/> <owl:Class rdf:ID=”Autor”/> Figura 4: Exemplo de classes na OWL. As propriedades descrevem os relacionamentos das classes e suas características. Na OWL, uma propriedade especifica uma relação binária entre conceitos. Por exemplo, a propriedade TemAutor liga um livro a um autor, demonstrando uma relação entre esses dois conceitos. Propriedades também podem ser classificadas como inversas. Neste caso, a propriedade inversa seria TemLivro, que relaciona o autor com o livro conforme ilustrado na figura 15 5. Ainda existem dois tipos de propriedades que não serão abordados aqui, que se denominam propriedades transitivas e as propriedades simétricas. Figura 5: Exemplo de propriedade OWL Para ilustrar melhor um documento OWL analisemos um trecho de documento exemplificado na Figura 5. As primeiras linhas que estão marcadas com a tag rdf:RDF fazem referencia ao vocabulário que está sendo utilizado neste documento. Os conceitos SigmodRecord, issue e volume são ditos Elementos raízes( ou indivíduos raízes). Um construtor taxômico fundamental para as classes é o subClassOf, este relaciona uma classe mais específica com outra classe mais genérica e que neste exemplo exibe o conceito SigmodRecord como sendo uma classe mais específica da classe dos Conceitos Não-Léxicos(NonLexicalConcept). 16 Figura 6: Exemplo de um documento OWL. Atualmente a OWL contem três sub-linguagens: OWL Lite que pode ser visto como uma versão mais simplificada da OWL, a OWL DL que aumenta a expressividade mantendo a decibilidade e a OWL Full que também aumenta a expressividade, porém não garante a decibilidade. 2.4. XPATH A XPath é uma linguagem de consulta que permite a navegação em um documento XML (XPath, 2005). Ela pode ser definida como uma linguagem de construção de expressões de caminho. Sua estrutura assemelha-se muito com a navegação em estruturas de diretórios, onde cada elemento no documento XML resulta em um item na expressão de caminho XPath. Expressões XPath descrevem nodos sempre de uma forma hierarquizada, ou seja, no sentido do elemento raiz para as folhas. Os principais tipos existentes na XPath são: elementos, atributos, texto, funções, nodos documento e comentários. Navegações em ambas as direções de um documento XML são possíveis na XPath, ou seja, pode-se consultar elementos 17 de forma ascendente ou descendente. O quadro abaixo exemplifica algumas consultas em XPath em cima do documento XML da Figura 1. Figura 7: Exemplos de Consultas XPath Outra linguagem de consulta para XML recomendada pela W3C é a XQuery, que possui maior número de recursos, como por exemplo, a possibilidade de definir junções entre dados XML e possibilidade de gerar um resultado com estrutura diferente da existente no documento XML. Porém, para os objetivos deste trabalho, a linguagem XPath, por ser mais simples e suficiente, é utilizada. 2.5. ORM Object Role Modeling (ORM) é um modelo de dados em nível conceitual, onde a aplicação é descrita em termos em que qualquer usuário poderia entendê-lo (HALPIN, 1996). Sua intenção é semelhante a de outros modelos conceituais, como o ER e a UML. Uma modelagem em ORM representa basicamente um conjunto de objetos (entidades ou valores) que usam regras (participam relacionamentos). Uma regra define uma associação binária entre objetos. de 18 Figura 8: Representação gráfica de uma modelagem ORM detalhando objetos léxicos (objetos tracejados) e não-léxicos (objetos contínuos) Dois tipos de conceitos estão presentes no modelo ORM: léxicos e não – léxicos. Conceitos léxicos contêm informações (conteúdo). Já os conceitos não-léxicos são agregadores, ou seja, se compõem de outros conceitos que podem ser léxicos ou não-léxicos representados como uma forma circular tracejada e não-tracejada respectivamente. A Figura 8 mostra uma modelagem simplificada de um livro em que este objeto é representado como não-léxico, pois o conceito livro agrega os objetos léxicos autor, preço e título representados como uma forma circular não-tracejada. Dois tipos de relacionamentos são suportados nessa estrutura: herança e associação, um exemplo de associação é relacionamento de livro e autor, onde um autor possui um ou mais livros e livro possui um ou mais autores. Na Figura vemos o objeto livro ligado a duas regras: nomeado por e nomeia que se parece com um retângulo. A seta dupla sobre o retângulo representa unicidade: cada objeto livro é nomeado por apenas um título. O círculo preto na 19 ponta da ligação representa obrigatoriedade: cada objeto livro é nomeado obrigatoriamente por um título. Os objetos léxicos nessa estrutura é que carregam informações a serem armazenadas. Pela sua semelhança na representação de dados de forma hierarquizada, como na XML, este modelo foi escolhido para representar os esquemas conceituais no BInXS. Outra característica do ORM que se difere dos outros modelos é a ausência de atributos. O ORM utiliza-se de uma forma mais enxuta, que são os conceitos léxicos. Qualquer conceito léxico pode participar de regras com vários objetos. Isso também acontece em uma hierarquia de dados XML, onde um mesmo tipo de elemento simples pode estar associado a vários elementos complexos. 3. AMBIENTE BInXS 3.1. Visão Geral O Sistema BInXS (Bottom-up Integration of XML Schemata) é uma solução para a integração semântica de esquemas XML. O processo de integração executado pelo BInXS possui 2 etapas: Conversão e Unificação, conforme mostra a Figura 9. A etapa de Conversão transforma cada esquema local XML de entrada em um esquema de acordo com o modelo conceitual canônico, ou seja o modelo padrão para a representação dos dados XML, que no caso é o modelo ORM. A partir destes esquemas, realiza-se a unificação para se obter um esquema global. 20 Figura 9: Etapas do BInXS(MELLO,2002). Conforme explicado anteriormente, para facilitar a compreensão do domínio da aplicação, é utilizado um modelo conceitual que seja capaz de expressar a estrutura lógica dos esquemas XML de entrada. O BInXS utiliza o modelo ORM, explicado na Seção 2.5. A Figura 10 mostra a vantagem de se utilizar um modelo conceitual para abstrair os esquemas XML local (supondo a utilização de XSDs), pois um esquema conceitual apresenta um alto poder de expressão, sendo capaz de abstrair diferentes representações hierárquicas de esquemas XML em um mesmo domínio. Nesta Figura, a modelagem representa autores, artigos e as universidades envolvidas nos artigos e onde os autores estão afiliados. As três XSDs representam três possíveis formas distintas de estruturar estes dados em XML. 21 Figura 10: Esquema Conceitual e XSDs (MELLO, 2000) A etapa de Conversão possui 3 sub-etapas, que são o pré-processamento, conversão e a reestruturação. Estas sub-etapas são detalhadas na seção 3.2. Na etapa de Unificação são resolvidos conflitos de representação entre componentes semanticamente semelhantes dos esquemas conceituais locais gerados, com o apoio de uma base de dados terminológica e intervenção de um usuário especialista, culminando na geração de um esquema conceitual global. Esta etapa não gera informações de mapeamento. Portanto, está fora do escopo deste trabalho. Uma vez gerado o esquema global pelo BInXS, um usuário pode formular consultas sobre o mesmo sem precisar conhecer em detalhes os esquemas XML originais, pois as intenções semânticas dos elementos estão expressas no esquema global. Para que uma consulta possa ser formulada e executada com 22 sucesso, é necessário manter informações de mapeamento entre o esquema global e os esquemas locais dos documentos XML originais. A geração e catalogação destas informações são feitas na etapa de Conversão e são asseguradas por este trabalho. 3.2. Etapa de Conversão Este trabalho está inserido nesta etapa do BInXS, pois a transformação do esquema XML em um esquema conceitual correspondente ocorre nesta etapa. Esta seção descreve o fluxo principal desta etapa para uma melhor compreensão dos processos a serem apresentados nos capítulos adiantes. Conforme visto anteriormente, o processo de conversão é subdivido em três sub-etapas (Figura 11): Pré-processamento, Conversão e Reestruturação. Figura 11: Arquitetura da Etapa de Conversão do BInXS(MELLO, 2000). A sub-etapa de Pré-processamento recebe como entrada um esquema XML descrito em XML Schema (XSD), que ao longo deste trabalho chamaremos de 23 Esquema XML Original. Esta sub-etapa tem como principal função realizar um refinamento no documento de entrada para facilitar o processamento do arquivo durante o processo. As principais tarefas desta sub-etapa são: (i) substituição de entidades, (ii) remoção de elementos componentes e atributos semanticamente irrelevantes, (iii) remoção de estruturas aninhadas internas, (iv) tratamento de elementos compostos opcionais ou com repetição e (v) alteração de nomes de elementos e atributos. Para esta sub-etapa são criados três tipos de catálogos de apoio à geração de mapeamento: (i) catálogo de elementos renomeados; (ii) catálogo de elementos removidos e; (iii)catálogo de elementos virtuais. Estes catálogos servirão como base de consulta ao longo do processamento às alterações ocorridas na sub-etapa de pré-processamento, uma vez que, ao ser removido um elemento, por exemplo, este ficará sem referência no documento. Os catálogos são detalhados na Seção 4.2. Na sub-etapa de Conversão, o esquema XML pré-processado é analisado e transformado, através de regras pré-definidas e eventual auxílio de um usuário especialista para a definição da intenção semântica de certos elementos, em um esquema conceitual preliminar em ORM. Nesta etapa, as regras de conversão são aplicadas no esquema XSD de entrada, gerando conceitos e relacionamentos, correspondente ao esquema XSD. Os conceitos gerados podem ser léxicos e não-léxicos, assim como os relacionamentos gerados podem ser de associação e herança, que são os tipos suportados pelo ORM. Durante essas conversões é que são geradas as informações de mapeamento, ou seja, para cada geração de conceito ou de relacionamento é registrada uma informação de mapeamento associada ao esquema conceitual. Tanto o esquema conceitual quanto as informações de mapeamento ficam registrados no documento OWL, que é o resultado da etapa de Conversão do BInXS. As regras de mapeamento aplicadas durante a conversão do esquema XSD são detalhadas nas Seções 4.3 e 4.4. 24 Por fim, a sub-etapa de Reestruturação converge todos os conceitos gerados nas sub-etapas anteriores em um documento OWL, respeitando as alterações realizadas no esquema conceitual preliminar e adicionando a cada elemento as informações de mapeamento. 4. MÓDULO DE GERAÇÃO DE MAPEAMENTOS Este capítulo descreve como foi desenvolvido o módulo de geração de informação de mapeamentos, que considera regras pré-definidas previstas para o BInXS (MELLO, 2002). As informações de mapeamento são utilizadas para localizar sem ambiguidade um tipo de elemento ou atributo no XSD correspondente (MELLO, 2002) referente a um conceito no esquema global. O documento XSD é o arquivo de entrada, que inicialmente, dentro da etapa de Conversão, é submetido ao pré-processamento. No pré- processamento do arquivo são gerados e populados os catálogos (ver Seção 4.2), que apoiarão o processo de mapeamento. Na sub-etapa seguinte, conversão, é que o módulo de mapeamento atua, realizando as consultas necessárias na base de catálogos para gerar expressões de caminho XPath que correspondem aos mapeamentos de elementos e atributos (detalhes na Seção 4.1). Na sub-etapa reestruturação o módulo de mapeamento disponibiliza informações de caminho, auxiliando a construção do documento OWL. A Figura 12 mostra as sub-etapas da Conversão que se comunicam com este módulo dentro do Sistema BInXS. 25 Figura 12: Fases de atuação do módulo de mapeamento. 4.1. Estratégia de Mapeamento O módulo de mapeamento tem a função de manter a correspondência dos conceitos do esquema conceitual com os elementos e atributos XML nas fontes de dados originais. Para tanto, ele usa uma estratégia que utiliza a linguagem XPath, ou seja, mapeamentos para os elementos, atributos e relacionamentos hierárquicos entre eles em um esquema XSD são definidos na linguagem XPath, pois ela é capaz de definir um caminho para qualquer elemento ou atributo, assim como navegações entre eles. O mapeamento dos conceitos léxicos e não-léxicos no esquema conceitual é definido por uma expressão de caminho absoluto XPath no esquema XSD para o elemento ou atributo correspondente. Um caminho absoluto XPath tem origem no elemento raiz do esquema XSD e descreve o caminho a ser seguido na navegação até o elemento ou atributo mapeado. Em alguns casos é possível que um elemento tenha mais de um caminho para o 26 elemento raiz da XSD. Neste caso, devem-se mapear todos os caminhos possíveis correspondente a esses elementos. O mapeamento dos relacionamentos no esquema conceitual é definido por uma expressão de caminho relativo XPath, demonstrando, de forma correspondente, como se alcança um elemento/atributo no esquema XSD a partir de outro elemento/atributo. Este processo irá mapear os relacionamentos em ambos os sentidos, visando facilitar as consultas no esquema global gerado posteriormente (Mello, 2002). Vários casos existem na geração de mapeamentos de relacionamentos, dependendo da forma como um elemento componente está definido no esquema XSD. Estes casos são descritos a seguir. Informações de elementos removidos durante o Pré-Procesamento não geram mapeamentos, pois não são gerados conceitos para eles. Essas informações são armazenadas no catálogo de elementos removidos (ver Seção 4.2). Mesmo assim, o módulo de mapeamento prevê a existência destes elementos na definição de expressões de caminho XPath, toda vez que uma navegação precisa passar por este elemento. Por isso, a consulta a este catálogo pelo o módulo é necessária durante a geração do mapeamento. Esta seção descreve as regras da etapa de conversão que geram informações de mapeamento, bem como os catálogos (MELLO 2002). 4.2. Catálogos de Mapeamento Na sub-etapa de Pré-processamento, três atividades geram informações para os catálogos temporários de mapeamento. Estes catálogos são mantidos em um banco de dados relacional, que dá apoio ao módulo de mapeamento. 4.2.1. Catálogo de Elementos Renomeados 27 Alguns elementos e/ou atributos podem ser renomeados na etapa de préprocessamento. Isto acontece para seja fornecido um novo nome com maior intenção semântica dentro do contexto. Para tanto, faz-se necessário o registro deste vínculo do nome novo no XSD pré-processado e o nome antigo no XSD original para que se tenha uma referência para este elemento original. Para esta catalogação, define-se uma tabela relacional com as seguintes colunas: Fonte, Nome e Nome Original. A coluna Fonte contém a localização e o nome do esquema XML que está sendo pré-processado, esta informação pode ser definida como uma URL ou um caminho no disco local. A coluna Nome informa o novo nome dado ao elemento no XML pré-processado. O seu nome antigo descrito no XML original fica armazenado na coluna Nome Original. Com este catálogo é possível encontrar qualquer elemento que foi renomeado do XML original para o XML pré-processado e ajustar uma expressão de caminho XPath para o nome original do elemento, quando um mapeamento precisar considera-lo. 4.2.2. Catálogo de Elementos Removidos Este catálogo mantém todos os elementos que não tem relevância semântica e forem removidos do esquema XML no pré-processamento. Por exemplo, um elemento do esquema que tem a finalidade de apenas encapsular outro grupo de outros elementos (como ListaDeAutores) é um candidato a ser removido do esquema. Uma tabela relacional com quatro colunas cataloga os elementos removidos. Ela possui a seguinte estrutura: Fonte, Elemento_Removido, Elemento_Pai e Elemento_Filho. A coluna Fonte tem função idêntica a da tabela anterior. A coluna Elemento_Removido armazena o nome do elemento que foi removido do esquema. Os campos Elemento_Pai e Elemento_Filho 28 guardam o nome dos elementos pai e filho, respectivamente, do elemento removido. Assim, é possível construir corretamente a expressão de caminho XPath para ele. 4.2.3. Catálogo de Elementos Virtuais Este catálogo armazena os elementos de uma estrutura aninhada anônima interna a um determinado elemento Ex do esquema XSD. Essa estrutura, se puder se repetir dentro de Ex, ou seja, tiver cardinalidade máxima N, não pode ser representada no esquema conceitual ORM, pois este não permite definir uma restrição do tipo “todos os elementos internos devem ocorrer N vezes juntos”. Para solucionar esse problema, são criados os chamados elementos virtuais, que encapsula esse conjunto de elementos aninhados da estrutura, tornando mais fácil a sua modelagem em nível conceitual. A tabela gerada para o armazenamento desse tipo de elemento tem a seguinte estrutura: o Nome da fonte XML e o Nome do elemento virtual definido nesta fonte. 4.3. Mapeamento de Conceitos 4.3.1. Mapeamento para um Elemento O mapeamento de um elemento expressa o caminho absoluto do elemento raiz até elemento desejado. Este caminho é composto dos elementos e seus relacionamentos percorridos a partir do elemento raiz do documento original até o elemento mapeado. 29 Figura 13: Trecho de uma XSD Com base na Figura 13, que demonstra um trecho de um XSD onde existe um elemento raiz denominado SigmodRecord, exemplifica-se o mapeamento para o elemento issues, que é definido pela seguinte expressão XPath: SigmodRecord/issues Caso não haja alteração de nome ou na estrutura de relacionamento do conceito correspondente a este elemento (informações estas mantidas nos catálogos), o mapeamento demonstrado acima é o resultado final do mapeamento deste conceito. 4.3.2. Mapeamento para um Atributo O mapeamento de um atributo assemelha-se com o mapeamento de um elemento. Este também expressa o caminho absoluto do elemento raiz até atributo em questão. Porém ao inserir o atributo na expressão, esse é precedido do caractere arroba (@) conforme ilustrado na Figura 14, que demonstra um comparativo de mapeamento de um conceito elemento e um conceito atributo. 30 Figura 14: Sintaxe do mapeamento para elemento e atributo. 4.4. Mapeamento de Relacionamentos 4.4.1. Mapeamento para um Elemento Componente Nomeado Este mapeamento refere-se à conversão de um elemento declarado (possui um nome) no modelo de conteúdo de um elemento pai, que ocorre uma única vez (cardinalidade máxima 1). O mapeamento entre um elemento pai E e um elemento componente E’, pode ser descrito da seguinte forma: Sentido E E’: Registram-se todos os elementos com origem em E até alcançar E’. Todos os elementos percorridos neste caminho devem levar em conta o seu nome no esquema XML inicial, caso tenham sido renomeados. Se E é um elemento virtual, este mapeamento é nulo, pois não existe correspondência com o esquema XML original, uma vez que os elementos virtuais são gerados na fase do pré-processamento; Sentido E E’: Contabilizam-se os n elementos a partir de E’ subindo n níveis hierárquicos até alcançar E. Cada relacionamento 31 no sentido inverso é representado por “..”, indicando que está subindo um (1) nível hierárquico. Se E é um elemento virtual, este mapeamento é nulo. Figura 15: Mapeamento dos elementos Livro e Endereço A Figura 15 mostra um exemplo de mapeamento relativo dos elementos Livro e Endereço, em ambos os sentidos do relacionamento conforme descrito anteriormente. Esta figura representa um fragmento da estrutura XML apresentada no início deste capítulo. Este mapeamento demonstrado na Figura é interpretado da seguinte forma: o mapeamento relativo entre o elemento Livro para o elemento Endereço se dá pela expressão XPath que percorre esse caminho. Partindo-se de Livro, o próximo elemento do trajeto inicia a expressão de caminho (Autor), 32 seguido do elemento Endereço, que é o destino final do mapeamento. Desse modo a expressão XPath gerada é Autor/Endereço. O mapeamento inverso se dá pelo número de níveis hierárquicos percorridos. Assim, para se alcançar o elemento Livro partindo do elemento Endereço, obtêm-se a seguinte expressão XPath: “../..”. 4.4.2. Mapeamento para um Elemento Componente Nomeado com Repetição Esse mapeamento ocorre toda vez que um elemento filho nomeado E’ é declarado duas vezes ou mais no modelo de conteúdo de um elemento pai E., ou seja, ele aparece várias vezes em posições determinadas no conteúdo do elemento pai. Este mapeamento é descrito na seguinte forma: E E’: Registram-se todos os elementos removidos com origem em E até alcançar E’. Este deve ser formado por seu nome original, caso tenha sido renomeado, ou o seu nome próprio, mais a expressão XPath [position() = i], onde i determina a posição do elemento filho e position() é uma função da XPath que restringe a navegação para a posição indicada. Caso E seja um elemento virtual, este mapeamento é nulo, pois não existe correspondência para este elemento no esquema inicial; E E’: Contabilizam-se os n elementos removidos a partir de E’ subindo n níveis hierárquicos até alcançar E. O relacionamento no sentido inverso é representado por “..”, indicando que está subindo um nível hierárquico. Se E é um elemento virtual, este mapeamento é nulo e é representado por “-”. Apesar dos elementos serem declarados com o mesmo nome, estes elementos podem ter intenções semânticas diferentes no contexto da estrutura XML. A intervenção de um usuário especialista neste caso é necessária para 33 análise através de uma análise no documento XML. Por exemplo, a primeira tag filha telefone de um elemento pessoa indica o seu telefone residencial, enquanto a segunda tag telefone é o seu celular. Detalhes sobre esta análise estão fora do escopo deste trabalho. Figura 16: Mapeamento elemento nomeado com repetição A Figura 16 exemplifica um caso de mapeamento para um elemento nomeado com repetição, considerando que o primeiro endereço refere-se à localização comercial, enquanto o segundo endereço indica a localização residencial do Autor. Assim, o mapeamento para o endereço residencial, por exemplo, é dado pela expressão XPath Endereço [position() = 2]. 4.4.3. Mapeamento para um Elemento Componente texto Este mapeamento é gerado para um elemento E que contém um componente textual (não-estruturado – comum em estruturas semi- estruturadas XML), que quando incluído no esquema conceitual, gera uma 34 conceito não-léxico. O mapeamento para este tipo de elemento é definido da seguinte forma: E EText[i].: Registram-se todos os elementos removidos com origem em E até alcançar E’. Este deve ser formado por seu nome original, caso tenha sido renomeado, ou o seu nome próprio, mais a expressão XPath [position() = i], onde i determina a posição do elemento. Caso E seja um elemento virtual, este mapeamento é nulo, pois não existe correspondência para este elemento no esquema inicial; E EText[i].: Caso existam elementos removidos entre os dois conceitos, este elementos devem ser levados em consideração. Caso contrário como não há deslocamento na hierarquia dos elementos para se alcançar E este mapeamento é nulo e representado por “-“. A Figura 17 ilustra este mapeamento, tomando como exemplo o componente end_page e seu relacionamento com um novo conceito léxico gerado denominado end_pageText, considerando que end_pageText representa a informação não-estruturada (textual) do elemento end_page. Neste exemplo como não existe elementos removidos entre os elementos end_page e end_pageText, o mapeamento do sentido end_page end_pageText é considerado nulo. 35 Figura 17: Mapeamento do conceito end_page e do relacionamento de elemento componente texto () 4.4.4. Mapeamento de Relacionamento de Herança A herança em um esquema XML é determinada por interpretação semântica, ou seja, verifica-se, com o auxílio de Thesauri, se um conceito criado é mais genérico ou mais específico que outro, determinando assim um relacionamento de herança entre eles (Mello, 2002). O mapeamento entre um elemento qualquer e um elemento mais genérico não é explicitamente definido em um esquema XML, pois assume-se que todo elemento especializado é um elemento genérico. Ao invés disso, 36 mapeamentos são definidos apenas entre elementos/atributos associados ao elemento genérico e seus elementos especializados. Figura 18: Mapeamento do relacionamento de herança Periódico-Titulo Na Figura 18, foi definido, por exemplo, que o elemento Periódico é uma especialização do elemento Publicação. Logo, um relacionamento de herança entre estes dois elementos é definido e um mapeamento entre os elementos Titulo e Periódico deve ser previsto. 4.4.5. Mapeamento de uma Qualificação Uma qualificação é uma política de conversão baseada também em uma interpretação semântica. Ela assume que um elemento vazio sem atributos é considerada uma propriedade (uma qualificação) do elemento que o contém (Mello, 2002). Uma vez identificado tal(is) sub-elementos, cria-se um conceito especial para eles, cujo nome é o nome do elemento que o(s) contem(ém) acompanhado do sufixo “Type”. A Figura 19 mostra um exemplo desta situação, onde os elementos Ativo e Aposentado são qualificações do elemento Professor. Estes dois elementos são incluídos em um conceito especial chamado ProfessorType, cujos valores permitidos são “Ativo” e “Aposentado”. Além disso, o mapeamento do conceito ProfessorType deve prever os caminhos alternativos para todos os seus componentes, como mostra a Figura 19. 37 Figura 19: Mapeamento do conceito ProfessorType e do relacionamento de uma qualificação Professor-ProfessorType Na Figura 19, o mapeamento do relacionamento ProfessorProfessorType é chamado de mapeamento dinâmico, pois são definidas alternativas em função do tipo de consulta que pode ser formulada no esquema conceitual global. O primeiro caso ocorre se uma consulta deseja apenas navegar de Professor para ProfessorType. Isto implica consultar todos os elementos que ProfessorType abstrai. O segundo caso refere-se a uma filtragem (do tipo “igual” ou “diferente de”) sobre algum valor de ProfessorType, ou seja, “Ativo” ou “Aposentado”. A função XPath local_name() neste caso é utilizada. Ela testa a existência de um elemento (uma tag) e com isso se descobre se o sub-elemento (no caso “Ativo” ou “Aposentado”) existem como tag filha. Por sua vez, o mapeamento inverso considera apenas um deslocamento na hierarquia de elementos até alcançar o elemento pai Professor. 4.4.6. Mapeamento para um Relacionamento com Elemento ANY Um elemento XML do tipo ANY aceita qualquer elemento do esquema como seu sub-elemento. Assim sendo, o mapeamento deste tipo de elemento 38 deve prever todos os possíveis relacionamentos que este elemento pode ter com os demais elementos do esquema (Mello, 2002). Figura 20: Mapeamento de relacionamento com um elemento ANY, entre os conceitos Coleção-Disco e Coleção-Video A Figura 20 mostra um exemplo de mapeamento de um elemento do tipo ANY definido em um DTD sobre coletânea de mídias audiovisuais. O elemento Coleção sendo do tipo ANY, pode assumir qualquer um dos elementos do DTD. Por isso, mapeamentos dele com todos os demais elementos devem ser previstos. 5. IMPLEMENTAÇÃO DO MÓDULO DE MAPEAMENTO 5.1. Tecnologias Utilizadas Neste trabalho optou-se por utilizar a tecnologia Java por esta ser a linguagem já adotada na implementação de outros módulos do Sistema BInXS. Para a manipulação da árvore do documento XSD que trafega entre as subetapas da etapa de Conversão, utiliza-se uma API presente no Java denominada JDOM. Esta API tem duas formas diferentes de realizar o parser 39 no documento XML de origem e assim construir a árvore do documento do esquema XSD em memória: DOM e SAX. Estes dois mecanismos trabalham de forma diferente na leitura e carga do documento XML. O parser DOM analisa o documento e carrega as informações de uma só vez para a memória, o que pode ocasionar problemas devido ao tamanho do documento XML e da memória utilizada neste processo. O parser SAX, por sua vez, trabalha com partes do documento, analisando-o de forma sequencial e estruturada. Para tanto, cria-se uma estrutura externa de elementos, que serão tratados através de eventos gerados e assim vão construindo a árvore em memória. Neste processo, a parte do documento que já foi processada é descartada, aumentando a memória disponível para o sistema. Em função desta vantagem na utilização da memória, este trabalho utiliza o SAX. Através de métodos presentes na API, como o SAXBuilder, podese carregar o documento XML e através das iterações geradas a cada elemento processar totalmente a arvore de elementos em memória. 5.2. Projeto de Classes Este trabalho estende a arquitetura de classes definida no trabalho de (GARCIA, 2005), que segue o modelo MVC. Este trabalho de conclusão de curso implementou a etapa de conversão do sistema BInXS. O presente trabalho estende o trabalho de (GARCIA, 2005) com a inclusão do módulo de mapeamento. O uso do modelo MVC facilita o entendimento da implementação, por ser um padrão de projeto de conhecimento público e bastante difundido na área de projeto de software(GAMMA et al.,2004). A Figura 21 mostra a estrutura do modelo MVC utilizado no trabalho de (GARCIA, 2005). 40 Figura 21: Estrutura do Modelo MVC (GAR 2005) O padrão de projeto MVC consiste em separar a arquitetura de classes em três camadas. Estas camadas são denominadas modelo, visão e controle. A camada de modelo implementa a estrutura lógica dos dados, enquanto a camada visão contém as classes que dão suporte a interface junto ao usuário. O controle por sua vez, realiza a junção dessas duas camadas citadas anteriormente, ou seja, ele tem a responsabilidade de realizar a comunicação entre o controle e a visão. A idéia básica do MVC é permitir que a lógica de negócio possa ser acessada através de várias interfaces, preocupando-se assim em separar a informação de sua apresentação. No sistema BinXS este padrão está definido da seguinte forma: a classe modelo representa a estrutura XML que é informada na entrada da conversão enquanto as classes controle são as etapas propriamente ditas da conversão. As etapas estão dividas em oito fases, sendo três no pré-processamento, cinco na conversão e uma na reestruturação. Essas são constituídas de regras específicas para cada fase. Essas regras estão detalhadas em (MELLO, 2002) e (GARCIA, 2005), não sendo explicadas neste trabalho. Finalmente, as classes visão são responsáveis por exibir os dados na forma em que cada uma foi designada. No BInXS, as classes de construção do arquivo OWL e da interface são exemplos de classe visão do modelo MVC. 41 5.3. Arquitetura da Catalogação Na sub-etapa de pré-processamento, o mapeamento faz-se presente através da alimentação dos catálogos. Logo, existe um catalogador que atua como uma visão no processo, ou seja, este recebe, por notificação das classes controle, todas as mudanças realizadas sobre os elementos. No préprocessamento, este catalogador é adicionado como observador do processo, conforme o padrão de projeto MVC modelado em (GARCIA, 2005). Para o processo de catalogação presente na sub-etapa de préprocessamento, foi-se implementado uma esquema no banco de dados relacional MySQL. Para utilizar a funcionalidade de armazenamento e consulta no banco de dados pelo Java, foi-se criado um componente bean no projeto que é responsável pelo o processo de acesso ao banco. Este bean contém três classes, sendo cada uma delas responsável pelo acesso a uma tabela especifica, ficando assim ElementosRemovidos.java, cada classe nomeada como: ElementosRenomeados.java, ElementosVirtuais.Java. Estas classes seguem basicamente o mesmo padrão das tabelas criadas no banco, ou seja, elas contem atributos idênticos aos das tabelas implementadas para uma melhor manipulação dos dados (conforme definições na Seção 4.2). Existe ainda, como base, uma classe Conexao.java que fornece apoio a parte de conexão ao banco propriamente dita, ou seja, esta classe implementa a parte de configuração de conexão ao banco. Os métodos principais desta classe são: Conexao() que carrega os parâmetros de conexão inicial com o banco, executeOrUpdate(String SQL) que realiza um comando SQL de inserção ou alteração no banco passado por parâmetro, executeSql(String Sql) que realiza um comando SQL de consulta ao banco e ainda o comando close() para evitar que sessões iniciadas ao banco fiquem pendentes após serem iniciadas e posteriormente utilizadas. 42 5.4. Arquitetura do Mapeamento Após o documento ser analisado na sub-etapa de pré-processamento, as conversões dos elementos em conceitos são realizadas na sub-etapa de conversão, dando origem, assim, à estrutura dos conceitos em uma árvore DOM. A partir dessa estrutura é que se baseia o mapeamento. Entre o final da sub-etapa de conversão e do início da sub-etapa de reestruturação é que se realiza o mapeamento propriamente dito, pois nesse momento do processo temos a estrutura DOM bem definida com seus respectivos conceitos contendo as anotações de mudanças do processo de conversão. O mapeamento realiza uma varredura nesta estrutura, gerando inicialmente os caminhos absolutos para cada elemento dessa árvore. A medida que os elementos são varridos também é feita uma consulta nos catálogos gerados no pré-processamento, pois é preciso conhecer o tipo de refinamento que o elemento possa ter sofrido, para que se respeite os dados originais do esquema XML da fonte durante o processo de mapeamento. Após a geração dos mapeamentos para cada elemento no esquema, o fluxo principal do processo é retomado, dando início ao processo de reestruturação e confecção do documento OWL. Neste passo, o objeto mapeador é passado como parâmetro para que o processo de reestruturação conheça as informações de mapeamento geradas para cada conceito presente no esquema resultante. Para cada classe de conceito no documento OWL é gerada uma subclasse de mapeamento de conceitos (MappingConcepts), onde é descrito o mapeamento na forma de expressões XPath. Nas classes de relacionamentos também é gerado uma subclasse denominada mapeamento de relacionamentos (RelationshipMappings), onde é descrito o mapeamentos direto e inverso do relacionamento referente a classe. 43 6. ESTUDO DE CASO Nesta seção será descrita o processo geral do processo de conversão levando em consideração todas as ações do ambiente que envolvem o módulo de mapeamento. 6.1. Fonte de Dados Inicialmente é definido um documento de entrada que é denominado como a fonte de dados, ou seja, a partir deste documento ocorrerá a conversão dos elementos e a futura integração de dados com outros esquemas de dados submetidos ao ambiente. O exemplo aqui proposto será o mapeamento do elemento number, que encontra-se na fonte de dados que estaremos utilizando denominado SigmodRecord.XSD , a figura 22 ilustra o trecho deste esquema pertinente ao estudo de caso apresentado. 44 Figura 22: Trecho do XSD SigmodRecord. 6.2. Pré-Processamento e Catalogação. Após submetido ao ambiente BInXS o esquema passa pelas sub-etapas da etapa conversão, a começar pelo o pré-processamento onde o esquema é refinado para a próxima sub-etapa, e a partir das alterações realizadas são populados os catálogos Neste caso apresentado, o elemento SigmodRecord é renomeado para o nome Periodico, e para esta alteração há uma ação do módulo no sentido de catalogar a operação conforme a figura 23, onde a tabela ElementoRenomeados registra o novo nome assim como o nome original 45 deste elemento. Assim como procedido com o elemento SigmodRecord também registra-se a alteração sofrida pelo o elemento IssueType, o qual foi removido do esquema e registrado na tabela de ElementosRemovidos. As tabelas catalogadas nesta sub-etapa é que serão referenciadas no momento que o módulo de mapeamento gerar os caminhos de expressão XPath, pois assim a referência a fonte original da informação não é perdida. Figura 23: Catalogação no pré-processamento. 6.3. Conversão e Geração do Mapeamento. Na etapa de conversão os elementos são convertidos em conceitos e relacionamentos respectivamente nesta ordem. A figura 24 ilustra o estado dos elementos no ambiente BInXS nos dois momentos de conversão desses elementos. 46 Figura 24: Inclusão de conceitos e relacionamentos na conversão. Após a conversão do esquema XSD em um esquema conceitual, a árvore é submetida ao módulo de mapeamento o qual gera os caminhos XPath para os mapeamentos de conceitos e relacionamentos. A figura 25 ilustra o processo geral do mapeamento, onde o mapeamento do elemento number é gerado a partir da árvore final do processo e em um segundo consulta-se os catálogos a fim de resgatar o caminho do elemento referenciando o a fonte original do dado. 6.4. Reestruturação e Informação de Mapeamento. Da sub-etapa de reestruturação é gerado o resultado da conversão tendo como saída o documento OWL. Durante a geração do documento e conforme os elementos são percorridos para a inclusão no OWL o mapeamento também é informado paralelamente. No estudo de caso apresentado a saída do processo de conversão se dá pelo o documento ilustrado na figura 25, onde 47 entre a linhas tracejadas estão destacadas as informações de mapeamento geradas no processo. Figura 25: Documento OWL contendo o mapeamento. 48 7. CONCLUSÃO Os catálogos na fase de pré-processamento foram implementados de acordo com as regras previstas em um banco relacional, porém é de grande valia a implementação dessa parte em um modelo independente de um Sistema Gerenciador de Banco de Dados (SGBD) a fim de melhorar a portabilidade do código-fonte e a própria execução do ambiente. A geração do mapeamento foi implementada em parte, pois os casos ID e IDREF não foram cobertos pelo o desenvolvimento. Os caminhos de mapeamento foram informados no documento OWL conforme marcações realizadas no trabalho de desenvolvimento da etapa de conversão, respeitando a sintaxe de caminho XPath. 7.1. Trabalhos Futuros Pela complexidade da ferramenta BInXS e para uma melhor dinâmica no processo de execução do sistema, uma interface gráfica é um aspecto a ser desenvolvido para esta solução. Uma interface que exiba os conceitos apresentados neste trabalho de forma gráfica e utilizando uma estrutura ORM, auxiliaria o usuário para um melhor entendimento do esquema resultante em uma etapa. A forma gráfica facilita a visualização do esquema de forma que o usuário especialista poderá realizar suas validações empregando um custo menor de esforço. O processo de catalogação foi desenvolvido sobre a arquitetura de um BD relacional (MySQL), para uma maior flexibilidade desta atividade e uma facilitação aos próximos trabalhos, um novo tipo de armazenamento para estas informações seria de grande auxílio, uma vez que para a execução do aplicativo e futuras implementações no ambiente BInXS o 49 usuário/desenvolvedor não necessitará instalar uma gama de aplicativos para a iteração completa dos processos realizados pelo o BInXS. 50 APÊNDICE A – Artigo 51 Geração de Informações de Mapeamento no Sistema de Integração e Esquemas XML BInXS. Eduardo Vaz de Mello T.B.1, Ronaldo S. Mello1 1 Departamento de Informática e Estatística – Universidade Federal de Santa Catarina (UFSC) Florianópolis – SC – Brazil {vaz,ronaldo}@inf.ufsc.br Resumo. Atualmente um dos maiores de consultas WEB é a dificuldade da integração de dados de fontes de origens distintas. Com base na flexibilidade da XML e na necessidade da unificação dos dados neste formato, foi idealizado o sistema BInXS (Mello; Heuser, 2005). BInXS tem como principal função a integração semântica de esquemas XML em um esquema global definitivo. As alterações realizadas durante este processo são passíveis de mapeamento, pois é necessário identificar que elemento ou atributo de um esquema XML local cada conceito no nível conceitual representa. 1. Introdução A XML (eXtensible Markup Language) é uma solução que permite a representação e o intercâmbio de informações entre sistemas, sob uma estrutura de um arquivo auto-descritivo, com grande legibilidade e de fácil entendimento (XML, 2005). A XML é um formato de arquivo que se assemelha muito com a HTML por também ser uma linguagem de marcação, ou seja, definir os dados de seus documentos através de tags. O Sistema BInXS (Bottom-up Integration of XML Schemata) é uma solução para a integração semântica de esquemas XML. O processo de integração executado pelo BInXS possui 2 etapas: Conversão e Unificação, conforme mostra a Figura 9. A etapa de Conversão transforma cada esquema local XML de entrada em um esquema de acordo com o modelo conceitual canônico, ou seja, o modelo padrão para a representação dos dados XML, que no caso é o modelo ORM. A partir destes esquemas, realiza-se a unificação para se obter um esquema global. Uma vez gerado o esquema global pelo BInXS, um usuário pode formular consultas sobre o mesmo sem precisar conhecer em detalhes os esquemas XML originais, pois as intenções semânticas dos elementos estão expressas no esquema global. Para que uma consulta possa ser formulada e executada com sucesso, é necessário manter informações de mapeamento entre o esquema global e os esquemas locais dos documentos XML originais. 2. BInXS 52 O Sistema BInXS (Bottom-up Integration of XML Schemata) é uma solução para a integração semântica de esquemas XML. O processo de integração executado pelo BInXS possui 2 etapas: Conversão e Unificação, conforme mostra a Figura 1. A etapa de Conversão transforma cada esquema local XML de entrada em um esquema de acordo com o modelo conceitual canônico, ou seja, o modelo padrão para a representação dos dados XML, que no caso é o modelo ORM. Figura 1: Etapas do BInXS(MELLO,2002). Para facilitar a compreensão do domínio da aplicação, é utilizado um modelo conceitual que seja capaz de expressar a estrutura lógica dos esquemas XML de entrada. O BInXS utiliza o modelo ORM. Este trabalho está inserido nesta etapa do BInXS, pois a transformação do esquema XML em um esquema conceitual correspondente ocorre nesta etapa. O processo de conversão é subdivido em três sub-etapas Pré-processamento, Conversão e Reestruturação. 3. Geração do Mapeamento O módulo de mapeamento tem a função de manter a correspondência dos conceitos do esquema conceitual com os elementos e atributos XML nas fontes de dados originais. Para tanto, ele usa uma estratégia que utiliza a linguagem XPath, ou seja, mapeamentos para os elementos, atributos e relacionamentos hierárquicos entre eles em um esquema XSD são definidos na linguagem XPath, pois ela é capaz de definir um caminho para qualquer elemento ou atributo, assim como navegações entre eles. O mapeamento dos conceitos léxicos e não-léxicos no esquema conceitual é definido por uma expressão de caminho absoluto XPath no esquema XSD para o elemento ou atributo correspondente. Um caminho absoluto XPath tem origem no elemento raiz do esquema XSD e descreve o caminho a ser seguido na navegação até o elemento ou atributo mapeado. Em alguns casos é possível que um elemento tenha mais de um caminho para o elemento raiz da XSD. Neste caso, devem-se mapear todos os caminhos possíveis correspondente a esses elementos. 3.1. Geração dos Catálogos 53 A sub-etapa de Pré-processamento recebe como entrada um esquema XML descrito em XML Schema . Esta sub-etapa tem como principal função realizar um refinamento no documento de entrada para facilitar o processamento do arquivo durante o processo. Para esta sub-etapa são criados três tipos de catálogos de apoio à geração de mapeamento: (i) catálogo de elementos renomeados; (ii) catálogo de elementos removidos e; (iii)catálogo de elementos virtuais. Estes catálogos servirão como base de consulta ao longo do processamento às alterações ocorridas na sub-etapa de pré-processamento, uma vez que, ao ser removido um elemento, por exemplo, este ficará sem referência no documento. A Figura 2 demonstra um exemplo de catalogação para os casos de Elementos Renomeados e Elementos Removidos. Figura 2: Catalogação de Elementos Renomeandos e Elementos Removidos 3.2. Geração do Mapeamento. Na sub-etapa de Conversão, o esquema XML pré-processado é analisado e transformado, através de regras pré-definidas e eventual auxílio de um usuário especialista para a definição da intenção semântica de certos elementos, em um esquema conceitual preliminar em ORM. Nesta etapa, as regras de conversão são aplicadas no esquema XSD de entrada, gerando conceitos e relacionamentos, correspondente ao esquema XSD. Os conceitos gerados podem ser léxicos e não-léxicos, assim como os relacionamentos gerados podem ser de associação e herança, que são os tipos suportados pelo ORM. Durante essas conversões é que são geradas as informações de mapeamento (XPath), ou seja, para cada geração de conceito ou de relacionamento é registrada uma informação de mapeamento associada ao esquema conceitual conforme ilustrado na Figura 3. Tanto o esquema conceitual quanto as informações de mapeamento ficam registrados no documento OWL, que é o resultado da etapa de Conversão do BInXS. 54 Figura 3: Mapeamento de elemento e atributo. 3.3. Reestruturação Nesta subetapa é gerado o documento final da etapa de conversão. Este documento de saída formatado em OWL descreve os conceitos, as relações destes, as informações semânticas de cada conceito e seus mapeamentos. A Figura 4 ilustra este documento com as informações de mapeamento para o elemento number. O primeiro trecho destacado refere-se ao mapeamento de conceito do elemento enquanto o segundo trecho descreve o mapeamento de relacionamento deste elemento com o elemento issue. Figura 4: Trecho documento OWL 4. Implementação O presente artigo estende o trabalho de (GARCIA, 2005) com a inclusão do módulo de mapeamento. O uso do modelo MVC facilita o entendimento da implementação, por ser um padrão de projeto de conhecimento público e bastante difundido na área de projeto de 55 software(GAMMA et al.,2004). A Figura 5 mostra a estrutura do modelo MVC utilizado no trabalho de (GARCIA, 2005). Figura 5: Estrutura do Modelo MVC (GAR 2005) Na sub-etapa de pré-processamento, o mapeamento faz-se presente através da alimentação dos catálogos. Logo, existe um catalogador que atua como uma visão no processo, ou seja, este recebe, por notificação das classes controle, todas as mudanças realizadas sobre os elementos. No pré-processamento, este catalogador é adicionado como observador do processo, conforme o padrão de projeto MVC modelado em (GARCIA, 2005). Após o documento ser analisado na sub-etapa de pré-processamento, as conversões dos elementos em conceitos são realizadas na sub-etapa de conversão, dando origem, assim, à estrutura dos conceitos em uma árvore DOM. A partir dessa estrutura é que se baseia o mapeamento. Entre o final da sub-etapa de conversão e do início da sub-etapa de reestruturação é que se realiza o mapeamento propriamente dito, pois nesse momento do processo temos a estrutura DOM bem definida com seus respectivos conceitos contendo as anotações de mudanças do processo de conversão. O mapeamento realiza uma varredura nesta estrutura, gerando inicialmente os caminhos absolutos para cada elemento dessa árvore. A medida que os elementos são varridos também é feita uma consulta nos catálogos gerados no pré-processamento, pois é preciso conhecer o tipo de refinamento que o elemento possa ter sofrido, para que se respeite os dados originais do esquema XML da fonte durante o processo de mapeamento. Após a geração dos mapeamentos para cada elemento no esquema, o fluxo principal do processo é retomado, dando início ao processo de reestruturação e confecção do documento OWL. Neste passo, o objeto mapeador é passado como parâmetro para que o processo de reestruturação conheça as informações de mapeamento geradas para cada conceito presente no esquema resultante. Para cada classe de conceito no documento OWL é gerada uma subclasse de mapeamento de conceitos (MappingConcepts), onde é descrito o mapeamento na forma de expressões XPath. 56 Nas classes de relacionamentos também é gerado uma subclasse denominada mapeamento de relacionamentos (RelationshipMappings), onde é descrito o mapeamentos direto e inverso do relacionamento referente a classe. 5. Conclusão O objetivo deste artigo é de elucidar a integração e a implementação do processo de geração de mapeamento com o processo de conversão no contexto do ambiente BInXS. Tal objetivo foi validado através de uma implementação de um módulo de mapeamento que salva as informações dentro do arquivo OWL que é responsável pela a persistência dos esquemas conceituais criados e que são gerados na saída do processo de conversão. Este trabalho é necessário neste ambiente para identificar que elemento ou atributo de um esquema XML local cada conceito no nível conceitual representa. Por exemplo, um conceito chamado Autor no esquema conceitual pode se referir às tags Escritor e Criador em duas fontes de dados XML diferentes, porem a partir da informação de mapeamento do conceito pode-se encontrar o elemento referente no XSD original de maneira não ambígua e determinística. Referências Abiteboul, S.; Buneman, P.; Suciu, D. Data on the Web: From Relations to Semistructured Data and XML. Morgan Kaufmann, San Francisco, California, 2000. Garcia, Leonardo Gonçalves. Uma ferramenta para engenharia reversa de esquemas XML em esquemas conceituais no ambiente BInXS. Florianópolis, 2005. Halpin, T. Business rules and object role modeling. Database Prog. and Design, v. 9,n. 10, p. 66_72, 1996. Mello, Ronaldo dos Santos. Uma abordagem bottom-up para a integração semântica de esquemas XML. Porto Alegre, 2002. Mello, Ronaldo dos Santos; HEUSER, Carlos Alberto. BInXS: A Process for Integration of XML Schemata.In: CAiSE 2005, Porto, Portugal, 2005. 57 APÊNDICE B – Código Fonte B.1 - BEAN package bean; /** * @author EM * @version 1.3 * @created 20 de Fevereiro de 2009 */ public class ElementosRemovidos { private int id; private String fonte; private String elementoRemovido; private String elementoPai; private String elementoFilho; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFonte() { return fonte; } public void setFonte(String fonte) { this.fonte = fonte; } public String getElementoRemovido() { return elementoRemovido; } public void setElementoRemovido(String elementoRemovido) { this.elementoRemovido = elementoRemovido; } public String getElementoPai() { return elementoPai; } public void setElementoPai(String elementoPai) { this.elementoPai = elementoPai; } public String getElementoFilho() { return elementoFilho; } public void setElementoFilho(String elementoFilho) { this.elementoFilho = elementoFilho; } } package bean; public class ElementosRenomeados { private int id; private String fonte; 58 private String nomeRenomeado; private String nomeOriginal; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFonte() { return fonte; } public void setFonte(String fonte) { this.fonte = fonte; } public String getNomeRenomeado() { return nomeRenomeado; } public void setNomeRenomeado(String nomeRenomeado) { this.nomeRenomeado = nomeRenomeado; } public String getNomeOriginal() { return nomeOriginal; } public void setNomeOriginal(String nomeOriginal) { this.nomeOriginal = nomeOriginal; } } package bean; /** * @author EM * @version 1.3 * @created 20 de Fevereiro de 2009 */ public class ElementosVirtuais { private int id; private String fonte; private String elementoVirtual; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFonte() { return fonte; } public void setFonte(String fonte) { this.fonte = fonte; } public String getElementoVirtual() { return elementoVirtual; } public void setElementoVirtual(String elementoVirtual) { this.elementoVirtual = elementoVirtual; } } B.2 - CONTROLE package controle; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import ed.Conceito; import ed.InterfaceElemento; import ed.Relacao; 59 /** * @author EM * @version 1.3 * @created 20 de Fevereiro de 2009 */ public class Mapeador { static LinkedList<LinkedList<Conceito>> caminho; public Mapeador() { }; public static void criaMapeamento(InterfaceElemento root, List<Conceito> conceitos, List<Relacao> relacionamentos, String nomeXSD) { System.out.println("***** INICIO MAPEAMENTO************************"); iniciaRoot(root, conceitos, relacionamentos, nomeXSD); imprimeXpath(); System.out.println("***** FIM MAPEAMENTO************************"); }; public static void iniciaRoot(InterfaceElemento root, List<Conceito> conceitos, List<Relacao> relacionamentos, String nomeXSD) { caminho = new LinkedList<LinkedList<Conceito>>(); LinkedList<Conceito> Lista = new LinkedList<Conceito>(); Conceito c = conceitos.get(0); Lista.add(c); caminho.add(Lista); List<Relacao> relacoesConceito = procureLigacoesComMencoesAConceito(c, relacionamentos); if (relacoesConceito.size() > 1) { for (int i = 0; i < relacoesConceito.size(); i++) { if (relacoesConceito.get(i).getConceito1().getConceito() == c .getConceito()) { geraMapeamento(root, relacoesConceito.get(0).getConceito2(), relacionamentos, nomeXSD, Lista); }; } } else if (relacoesConceito.size() == 1) { if (relacoesConceito.get(0).getConceito1().getConceito() == c .getConceito()) { 60 geraMapeamento(root, relacoesConceito.get(0).getConceito2(), relacionamentos, nomeXSD, Lista); }; } } public static void geraMapeamento(InterfaceElemento root, Conceito c, List<Relacao> relacionamentos, String nomeXSD, LinkedList<Conceito> L) { LinkedList<Conceito> ListaNova = new LinkedList<Conceito>(); ListaNova.addAll(L); ListaNova.add(c); caminho.addLast(ListaNova); List<Relacao> relacoesConceito = procureLigacoesComMencoesAConceito(c, relacionamentos); if (relacoesConceito.size() > 1) { for (int i = 0; i < relacoesConceito.size(); i++) { if (relacoesConceito.get(i).getConceito1().getConceito() == c .getConceito()) { geraMapeamento(root, relacoesConceito.get(i).getConceito2(), relacionamentos, nomeXSD, ListaNova); } ; } } else if (relacoesConceito.size() == 1) { if (relacoesConceito.get(0).getConceito1().getConceito() == c .getConceito()) { geraMapeamento(root, relacoesConceito.get(0).getConceito2(), relacionamentos, nomeXSD, ListaNova); }; } } public static void imprimeXpath() { System.out .println("<------ INICIO MAPEAMENTO DE CONCEITOS -------------->"); LinkedList<Conceito> List1 = new LinkedList<Conceito>(); for (Iterator iter = caminho.iterator(); iter.hasNext();) { List1 = (LinkedList<Conceito>) iter.next(); 61 String xpath = ""; String e = ""; String r = ""; for (Iterator i = List1.iterator(); i.hasNext();) { Conceito c = (Conceito) i.next(); if (c.getRegra() == "AT") { xpath = xpath + "/@" + c.getConceito(); } else { xpath = xpath + "/" + c.getConceito(); } e = c.getConceito(); } System.out.println("Caminho: " + e + " xpath: " + xpath); } System.out .println("<------ FIM MAPEAMENTO DE CONCEITOS -------------->"); } private static LinkedList<Relacao> procureLigacoesComMencoesAConceito( Conceito conc, List<Relacao> relacoes) { LinkedList<Relacao> resposta = new LinkedList<Relacao>(); for (int i = 0; i < relacoes.size(); i++) if (relacoes.get(i).getConceito1().equals(conc) || relacoes.get(i).getConceito2().equals(conc)) resposta.addLast(relacoes.get(i)); return resposta; } public static String informaMapeamentoConceito(Conceito c) { String xpath = ""; LinkedList<Conceito> List1 = new LinkedList<Conceito>(); for (Iterator iter = caminho.iterator(); iter.hasNext();) { List1 = (LinkedList<Conceito>) iter.next(); if (List1.getLast() == c) { for (Iterator i = List1.iterator(); i.hasNext();) { Conceito conc = (Conceito) i.next(); if (conc.getRegra() == "AT") { xpath = xpath + "/@" + conc.getConceito(); } else { 62 xpath = xpath + "/" + conc.getConceito(); } } } } return (xpath); } public static String informaMapeamentoRelativoDireto(Conceito c1, Conceito c2) { String xpath = ""; LinkedList<Conceito> List1 = new LinkedList<Conceito>(); for (Iterator iter = caminho.iterator(); iter.hasNext();) { List1 = (LinkedList<Conceito>) iter.next(); if (List1.getLast() == c2) { boolean mapeia = false; for (Iterator i = List1.iterator(); i.hasNext();) { Conceito conc = (Conceito) i.next(); if (mapeia) { if (conc.getRegra() == "AT") { xpath = xpath + "/@" + conc.getConceito(); } else { xpath = xpath + "/" + conc.getConceito(); } } if (conc == c1) { mapeia = true; } } } } return (xpath); } public static String informaMapeamentoRelativoInverso(Conceito c1, Conceito c2) { String xpath = ""; LinkedList<Conceito> List1 = new LinkedList<Conceito>(); for (Iterator iter = caminho.iterator(); iter.hasNext();) { List1 = (LinkedList<Conceito>) iter.next(); if (List1.getLast() == c2) { boolean mapeia = false; 63 for (Iterator i = List1.iterator(); i.hasNext();) { Conceito conc = (Conceito) i.next(); if (mapeia) { if (conc.getRegra() != "AT") { xpath = xpath + "/.."; } } if (conc == c1) { mapeia = true; } } } } return (xpath); } } package controle; import interfac.AbstractInterface; import java.util.Set; import ed.InterfaceElemento; /** * @author Leo * @version 1.3 * @created 28 de Novembro de 2005 */ public abstract class AbstractEtapas extends AbstractMudancas { protected String nomeArqSaida; public AbstractEtapas(AbstractInterface i, Set<AbstractObserver> observadores) { super(i, observadores); } /** * Varre todos os tratadores pertencentes a uma subEtapa e os delega o * processamento do elemento passado como parâmetro * * @param e * Elemento para ser processado */ public abstract void trateElemento(InterfaceElemento e); /** * Retorna o nome do arquivo temporário gerado por esta etapa * * @return String Nome do arquivo temporário */ public String qualArquivoSaida() { return nomeArqSaida; } } package controle; 64 import interfac.AbstractInterface; import java.util.Set; import ed.MudancaElemento; /** * @author Leo * @version 1.4 * @created 28 de Novembro de 2005 */ public abstract class AbstractMudancas extends AbstractSubject { protected MudancaElemento mudanca; public AbstractMudancas(AbstractInterface i, Set<AbstractObserver> observadores) { super(i, observadores); i.setSubject(this); for (AbstractObserver obs : observadores) obs.setSubject(this); } /** * Retorna a mudança gerada pelos tratadores * * @return MudancaElemento Informações gerados pelos tratadores que devem * ser de conhecimento público */ public final MudancaElemento get() { return mudanca; } /** * Atualiza a mudança gerada por aquela passada como parâmetro * * @param MudancaElemento * Nova mudança gerada */ protected void setMudanca(MudancaElemento m) { mudanca = m; } } package controle; import ed.MudancaElemento; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public abstract class AbstractObserver { protected MudancaElemento mudanca; protected AbstractMudancas assunto; protected abstract void update(); /** * Atualiza para quem o observador estará esperando a notificação de * mudancas * * @param AbstractMudancas 65 * Instância de uma classe que guarda mudanças ocorridas no * sistema */ public final void setSubject(AbstractMudancas ass) { assunto = ass; } } package controle; import interfac.AbstractInterface; import java.util.HashSet; import java.util.Set; /** * @author Leo * @version 1.3 * @created 28 de Novembro de 2005 */ public abstract class AbstractSubject { protected Set<AbstractObserver> observadores; public AbstractSubject(AbstractInterface i, Set<AbstractObserver> observers) { observadores = new HashSet<AbstractObserver>(); this.attachObserver(i); for (AbstractObserver obs : observers) this.attachObserver(obs); } /** * Adiciona um observador para que este seja notificado de mudanças * ocorridas no sistema * * @param Observador * Instância que deseja ser notificada de mudanças */ protected final void attachObserver(AbstractObserver o) { observadores.add(o); } /** * Retira um observador para que este não mais seja notificado de mudanças * ocorridas no sistema * * @param Observador * Instância que deseja-se retirar da lista de notificações */ protected final void detachObserver(AbstractObserver o) { observadores.remove(o); } /** * Após a geração de uma mudança este método se encabe de notificar todos os * módulos anexados */ protected final void notifyEveryOne() { for (AbstractObserver o : observadores) { o.update(); 66 } } } package controle; import interfac.Interface; import java.util.LinkedList; import modelo.DOMWriter; import ed.Conceito; import ed.InterfaceElemento; import ed.MudancaElemento; import ed.Relacao; /** * @author Leo * @version 1.12 * @created 28 de Novembro de 2005 */ public class ConstrutorOWL extends AbstractObserver { private static final Mapeador Mapeador = null; Interface interf; LinkedList<Conceito> conceitos; LinkedList<Relacao> relacoes; LinkedList<LinkedList<Relacao>> disjuntivosEntreSi; String regraAnterior; String nomeXSD; public ConstrutorOWL(Interface i, String nomeXSD) { this.nomeXSD = nomeXSD; interf = i; conceitos = new LinkedList<Conceito>(); relacoes = new LinkedList<Relacao>(); disjuntivosEntreSi = new LinkedList<LinkedList<Relacao>>(); regraAnterior = ""; } /* * (non-Javadoc) * * @see controle.AbstractObserver#update() */ protected void update() { mudanca = assunto.get(); // HerTT a relacao significa heranca if (mudanca.getClass().getSimpleName().equals("Conceito")) { if (!conceitos.contains(mudanca)) { conceitos.addLast((Conceito) mudanca); System.out.println("Recebeu a mudanca: " + mudanca); } } else { if (((Relacao) mudanca).getRegra().equals("ATAny")) { LinkedList<Relacao> novaDisjuntividade = new LinkedList<Relacao>(); for (int i = 0; i < conceitos.size(); i++) if (conceitos.get(i).getRegra().equals("AT") || conceitos.get(i).getRegra().equals("ES")) { 67 Relacao novaRel = new Relacao("ATAny", ((Relacao) mudanca).getConceito1(), conceitos .get(i), ((Relacao) mudanca) .getCardDireta1(), ((Relacao) mudanca) .getCardDireta2(), ((Relacao) mudanca) .getCardInversa1(), ((Relacao) mudanca) .getCardInversa2()); this.monteRelacao(novaRel); novaDisjuntividade.addLast(novaRel); } disjuntivosEntreSi.addLast(novaDisjuntividade); } else if (((Relacao) mudanca).getRegra().equals("RTEC")) { LinkedList<Relacao> ligacoes = new LinkedList<Relacao>(); ligacoes = this.procureLigacoesDiretas(((Relacao) mudanca) .getConceito2()); for (int i = 0; i < ligacoes.size(); i++) this.monteRelacao(new Relacao(ligacoes.get(i).getRegra(), ((Relacao) mudanca).getConceito1(), ligacoes.get(i) .getConceito2(), ligacoes.get(i) .getCardDireta1(), ligacoes.get(i) .getCardDireta2(), ligacoes.get(i) .getCardInversa1(), ligacoes.get(i) .getCardInversa2())); } else if (((Relacao) mudanca).getRegra().equals("RTES")) { Conceito elemento = this.retorneConceito(((Relacao) mudanca) .getConceito1()); Conceito tipoSimples = this.retorneConceito(((Relacao) mudanca) .getConceito2()); elemento.getAnotacoes().addAll(tipoSimples.getAnotacoes()); } else if (((Relacao) mudanca).getRegra().equals("RAny")) { LinkedList<Relacao> novaDisjuntividade = new LinkedList<Relacao>(); for (int i = 0; i < conceitos.size(); i++) if (!conceitos.get(i).getRegra().equals("AT") && !conceitos.get(i).getRegra().equals("T") && !conceitos.get(i).getRegra().equals("ATAny")) { Relacao novaRel = new Relacao("RAny", ((Relacao) mudanca).getConceito1(), conceitos .get(i), ((Relacao) mudanca) 68 .getCardDireta1(), ((Relacao) mudanca) .getCardDireta2(), ((Relacao) mudanca) .getCardInversa1(), ((Relacao) mudanca) .getCardInversa2()); this.monteRelacao(novaRel); novaDisjuntividade.addLast(novaRel); } disjuntivosEntreSi.addLast(novaDisjuntividade); } else if (((Relacao) mudanca).getRegra().equals("HerTE")) { LinkedList<Relacao> ligacoes = new LinkedList<Relacao>(); ligacoes = this.procureLigacoesDiretas(((Relacao) mudanca) .getConceito2()); for (int i = 0; i < ligacoes.size(); i++) if (!ligacoes.get(i).getRegra().equals("HerTT")) this.monteRelacao(new Relacao(ligacoes.get(i) .getRegra(), ((Relacao) mudanca).getConceito1(), ligacoes .get(i).getConceito2(), ligacoes.get(i) .getCardDireta1(), ligacoes.get(i) .getCardDireta2(), ligacoes.get(i) .getCardInversa1(), ligacoes.get(i) .getCardInversa2())); else { LinkedList<Relacao> ligacoesHerTT = new LinkedList<Relacao>(); ligacoesHerTT = this.procureLigacoesDiretas(ligacoes .get(i).getConceito2()); for (int j = 0; j < ligacoesHerTT.size(); j++) this.monteRelacao(new Relacao(ligacoesHerTT.get(j) .getRegra(), ((Relacao) mudanca) .getConceito1(), ligacoesHerTT.get(j) .getConceito2(), ligacoesHerTT.get(j) .getCardDireta1(), ligacoesHerTT.get(j) .getCardDireta2(), ligacoesHerTT.get(j) .getCardInversa1(), ligacoesHerTT.get(j) .getCardInversa2())); } } else if (((Relacao) mudanca).getRegra().equals("Disj")) { if (!regraAnterior.equals("Disj")) { 69 LinkedList<Relacao> novaDisjuntividade = new LinkedList<Relacao>(); novaDisjuntividade.addLast(this.retorneLigacao( ((Relacao) mudanca).getConceito1(), ((Relacao) mudanca).getConceito2())); disjuntivosEntreSi.addLast(novaDisjuntividade); } else disjuntivosEntreSi.getLast().addLast( this.retorneLigacao(((Relacao) mudanca) .getConceito1(), ((Relacao) mudanca) .getConceito2())); } else if (((Relacao) mudanca).getRegra().equals("RUnion")) { if (!regraAnterior.equals("RUnion")) { LinkedList<Relacao> novaDisjuntividade = new LinkedList<Relacao>(); this.monteRelacao(mudanca); novaDisjuntividade.addLast(this.retorneLigacao( ((Relacao) mudanca).getConceito1(), ((Relacao) mudanca).getConceito2())); disjuntivosEntreSi.addLast(novaDisjuntividade); } else { this.monteRelacao(mudanca); disjuntivosEntreSi.getLast().addLast( this.retorneLigacao(((Relacao) mudanca) .getConceito1(), ((Relacao) mudanca) .getConceito2())); } } else if (((Relacao) mudanca).getRegra().equals("RemT")) { this.removaMencoesATipos(); try { this.monteArquivoOWL(); } catch (Throwable e) { interf .recebaInformacoes("ERRO FATAL NA CRIAÇÃO DO ARQUIVO OWL:" + e.getMessage()); e.printStackTrace(); System.exit(1); } } else this.monteRelacao(mudanca); regraAnterior = mudanca.getRegra(); } } private void removaMencoesATipos() { LinkedList<Relacao> relacoesSemTipos = new LinkedList<Relacao>(); // de todas as relacoes eliminam-se aquelas que existem referancias a // conceitos criados pela regra 'T' for (int i = 0; i < relacoes.size(); i++) { 70 Conceito c1 = this.retorneConceito(relacoes.get(i).getConceito1()); Conceito c2 = this.retorneConceito(relacoes.get(i).getConceito2()); if (!c1.getRegra().equals("T") && !c2.getRegra().equals("T")) relacoesSemTipos.addLast(relacoes.get(i)); else { // retira-se dos disjuntivos alguma regra que contenha conceitos // gerados pela regra 'T' int index = 0; while (index < disjuntivosEntreSi.size()) { if (disjuntivosEntreSi.get(index).contains(relacoes.get(i))) disjuntivosEntreSi.get(index).remove(relacoes.get(i)); if (disjuntivosEntreSi.get(index).size() == 0) disjuntivosEntreSi.remove(index); else index++; } } } relacoes = relacoesSemTipos; // excluem-se os conceitos gerados pela regra 'T' LinkedList<Conceito> conceitosSemTipos = new LinkedList<Conceito>(); for (int i = 0; i < conceitos.size(); i++) { if (!conceitos.get(i).getRegra().equals("T")) conceitosSemTipos.addLast(conceitos.get(i)); } conceitos = conceitosSemTipos; } private Relacao retorneLigacao(Conceito conceito1, Conceito conceito2) { for (int i = 0; i < relacoes.size(); i++) if ((relacoes.get(i).getConceito1().getConceito().equals(conceito1 .getConceito())) && (relacoes.get(i).getConceito2().getConceito() .equals(conceito2.getConceito()))) return relacoes.get(i); return null; } private Conceito retorneConceito(Conceito c) { for (int i = 0; i < conceitos.size(); i++) if (conceitos.get(i).getConceito().equals(c.getConceito())) return conceitos.get(i); return null; } 71 private LinkedList<Relacao> procureLigacoesDiretas(Conceito conc) { LinkedList<Relacao> resposta = new LinkedList<Relacao>(); for (int i = 0; i < relacoes.size(); i++) if (relacoes.get(i).getConceito1().equals(conc)) resposta.addLast(relacoes.get(i)); return resposta; } private void monteRelacao(MudancaElemento m) { int c1 = conceitos.indexOf(((Relacao) m).getConceito1()); int c2 = conceitos.indexOf(((Relacao) m).getConceito2()); if (c1 != -1 && c2 != -1) { Conceito con1 = conceitos.get(c1); Conceito con2 = conceitos.get(c2); relacoes.addLast(new Relacao(((Relacao) m).getRegra(), con1, con2, ((Relacao) m).getCardDireta1(), ((Relacao) m) .getCardDireta2(), ((Relacao) m).getCardInversa1(), ((Relacao) m).getCardInversa2())); System.out.println("--Recebida a mudanca: " + m); } else { interf .recebaInformacoes("Erro na criação da relação no ContrutorOWL!"); System.exit(1); } } private void monteArquivoOWL() throws Throwable { DOMWriter saida = new DOMWriter("leogoga.txt"); InterfaceElemento root = saida.getRoot(); Mapeador.criaMapeamento(root, conceitos, relacoes, nomeXSD); Output.criaConceitosOWL(root, conceitos, relacoes, nomeXSD, Mapeador); Output.criaRelacoesOWL(root, relacoes, disjuntivosEntreSi, nomeXSD); saida.output(root); } } package controle; import dao.ElementoRenomeadoDAO; import dao.ElementosRemovidosDAO; import dao.ElementosVirtuaisDAO; import bean.ElementosRemovidos; import bean.ElementosRenomeados; import bean.ElementosVirtuais; public class ControleMain { public void insereElementosRemovidos(ElementosRemovidos e){ ElementosRemovidosDAO erDAO = new ElementosRemovidosDAO(); erDAO.insere(e); } 72 public void insereElementosRenomeados(ElementosRenomeados e){ ElementoRenomeadoDAO erDAO = new ElementoRenomeadoDAO(); erDAO.insere(e); } public void insereElementosVirtuais(ElementosVirtuais e){ ElementosVirtuaisDAO erDAO = new ElementosVirtuaisDAO(); erDAO.insere(e); } } package controle; import modelo.DOMReader; import modelo.InterfaceReader; import ed.InterfaceElemento; /** * @author Leo * @version 1.4 * @created 28 de Novembro de 2005 */ public class Evento { protected InterfaceReader modelo; protected ProcessoMain main; public Evento() { modelo = new DOMReader(); } public Evento(ProcessoMain main) { modelo = new DOMReader(); this.main = main; } /** * Método responsável por se comunicar com o acesso à dados do programa. Os * nomes da fonte XSD e o arquivo que deve ser gerado após seu processamento * são passados como parâmetro * * @param arq * Nome do arquivo fonte XSD * @param arqSaida * Nome do arquivo temporário criado após o processamento da * fonte XSD * @throws Throwable */ public void abrirArquivo(String arq, String arqSaida) throws Throwable { modelo.makeData(arq, arqSaida, this); } /** 73 * Método responsável por se comunicar com o acesso à dados do programa. * Recebe os elementos gerados e os repassa ao ProcessoMain para tratamento * adequado * * @param e * Elemento criado pelo acesso a dados */ public void recebeElemento(InterfaceElemento e) { main.trateElemento(e); } } package controle; import java.util.LinkedList; import java.util.List; import ed.Conceito; import ed.Elemento; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.4 * @created 28 de Novembro de 2005 */ public class Output { /** * Passado a lista de Conceitos e o elemento root do arquivo de saída OWL * esse método se encarrega de fazer a estruturação do arquivo segundo as * regras anexadas no trabalho de Leonardo Garcia(2005) * * @param root * Elemento root do arquivo OWL * @param conceitos * Lista de conceitos para serem estruturados * @param relacionamentos * Lista dos relacionamentos entre os Conceitos passados como * parâmetro * @param nomeXSD * Nome do arquivo fonte XSD */ public static void criaConceitosOWL(InterfaceElemento root, List<Conceito> conceitos, List<Relacao> relacionamentos, String nomeXSD, Mapeador m) { Elemento concOWL; for (Conceito c : conceitos) { String tipo = ""; String[] enumer = null; for (String s : c.getAnotacoes()) { 74 if (s.matches("tipo=.*")) tipo = s.substring(s.indexOf("=") + 1, s.length()); else if (s.matches("enumeracao=.*")) { enumer = s.split(","); enumer[0] = enumer[0].substring(enumer[0].indexOf("[") + 1, enumer[0].length()); enumer[enumer.length - 1] = enumer[enumer.length 1] .substring(0, enumer[enumer.length - 1].length() - 1); for (int h = 0; h < enumer.length; h++) enumer[h] = enumer[h].trim(); } } concOWL = new Elemento("Class"); concOWL.addAttribute("ID", c.getConceito()); InterfaceElemento subClassOf = new Elemento("subClassOf"); if (c.ehLexico()) { if (enumer != null) subClassOf.addAttribute("resource", "#EnumeratedLexicalConcept"); else subClassOf.addAttribute("resource", "#LexicalConcept"); } else subClassOf.addAttribute("resource", "#NonLexicalConcept"); concOWL.addContent(subClassOf); subClassOf = new Elemento("subClassOf"); if (!tipo.equals("")) { InterfaceElemento restrictionLex = new Elemento("restriction"); restrictionLex.addAttribute("hasValue", tipo); InterfaceElemento onPropertyLex = new Elemento("onProperty"); onPropertyLex.addAttribute("resource", "#DataType"); restrictionLex.addContent(onPropertyLex); subClassOf.addContent(restrictionLex); } InterfaceElemento restriction = new Elemento("restriction"); subClassOf.addContent(restriction); InterfaceElemento onProperty; InterfaceElemento toClass; List<Relacao> relacoesConceito = procureLigacoesComMencoesAConceito( c, relacionamentos); if (relacoesConceito.size() > 1) { onProperty = new Elemento("onProperty"); 75 onProperty.addAttribute("resource", "#RelatedConcepts"); restriction.addContent(onProperty); toClass = new Elemento("toClass"); onProperty.addContent(toClass); InterfaceElemento UnionOf = new Elemento("UnionOf"); UnionOf.addAttribute("parseType", "collection"); toClass.addContent(UnionOf); for (int i = 0; i < relacoesConceito.size(); i++) { InterfaceElemento Thing = new Elemento("Thing"); Thing.addAttribute("about", "#" + relacoesConceito.get(i).getConceito1() .getConceito() + relacoesConceito.get(i).getConceito2() .getConceito()); UnionOf.addContent(Thing); } } else if (relacoesConceito.size() == 1) { onProperty = new Elemento("onProperty"); onProperty.addAttribute("resource", "#RelatedConcepts"); restriction.addContent(onProperty); toClass = new Elemento("toClass"); toClass.addAttribute("resource", "#" + relacoesConceito.get(0).getConceito1().getConceito() + relacoesConceito.get(0).getConceito2().getConceito()); onProperty.addContent(toClass); } onProperty = new Elemento("onProperty"); onProperty.addAttribute("resource", "#ConceptMappings"); toClass = new Elemento("toClass"); toClass.addAttribute("resource", "#" + c.getConceito() + " " + m.informaMapeamentoConceito(c)); onProperty.addContent(toClass); restriction.addContent(onProperty); // ver léxico aqui if (enumer != null) { onProperty = new Elemento("onProperty"); onProperty.addAttribute("resource", "#AllowedValues"); InterfaceElemento restriction2 = new Elemento("restriction"); for (int j = 0; j < enumer.length; j++) { InterfaceElemento enumeration = new Elemento("enumeration"); enumeration.addAttribute("value", enumer[j]); restriction2.addContent(enumeration); } onProperty.addContent(restriction2); restriction.addContent(onProperty); } concOWL.addContent(subClassOf); root.addContent(concOWL); 76 } } private static LinkedList<Relacao> procureLigacoesComMencoesAConceito( Conceito conc, List<Relacao> relacoes) { LinkedList<Relacao> resposta = new LinkedList<Relacao>(); for (int i = 0; i < relacoes.size(); i++) if (relacoes.get(i).getConceito1().equals(conc) || relacoes.get(i).getConceito2().equals(conc)) resposta.addLast(relacoes.get(i)); return resposta; } /** * Passado a lista de Relacionamentos e o elemento root do arquivo de saída * OWL esse método se encarrega de fazer a estruturação do arquivo segundo * as regras anexadas no trabalho de Leonardo Garcia(2005) * * @param root * Elemento root do arquivo OWL * @param relacoes * Lista de Relacoes existentes * @param disjuntivosEntreSi * Lista das disjunções entre os relacionamentos passados como * parâmetro * @param nomeXSD * Nome do arquivo fonte XSD */ public static void criaRelacoesOWL(InterfaceElemento root, LinkedList<Relacao> relacoes, LinkedList<LinkedList<Relacao>> disjuntivosEntreSi, String nomeXSD) { Elemento relacaoOWL; for (Relacao r : relacoes) { relacaoOWL = new Elemento("Class"); relacaoOWL.addAttribute("ID", r.getConceito1().getConceito() + r.getConceito2().getConceito()); InterfaceElemento subClassOf = new Elemento("subClassOf"); if (!r.getRegra().equals("HerTT")) { subClassOf.addAttribute("resource", "#AssociationRelationship"); relacaoOWL.addContent(subClassOf); subClassOf = new Elemento("subClassOf"); } else { subClassOf.addAttribute("resource", "#InheritanceRelationship"); relacaoOWL.addContent(subClassOf); subClassOf = relacaoOWL; } LinkedList<LinkedList<Relacao>> disjuncao = pertenceADisjuncoes(r, disjuntivosEntreSi); if (disjuncao.size() > 0) 77 for (int i = 0; i < disjuncao.size(); i++) for (int j = 0; j < disjuncao.get(i).size(); j++) if (!disjuncao.get(i).get(j).equals(r)) { InterfaceElemento disjointWith = new Elemento( "disjointWith"); disjointWith.addAttribute("resource", "#" + disjuncao.get(i).get(j).getConceito1() .getConceito() + disjuncao.get(i).get(j).getConceito2() .getConceito()); relacaoOWL.addContent(disjointWith); } InterfaceElemento restriction = new Elemento("restriction"); restriction.addAttribute("toClass", r.getConceito1().getConceito()); InterfaceElemento onProperty = new Elemento("onProperty"); onProperty.addAttribute("resource", "#SourceConcept"); restriction.addContent(onProperty); subClassOf.addContent(restriction); restriction = new Elemento("restriction"); restriction.addAttribute("toClass", r.getConceito2().getConceito()); onProperty = new Elemento("onProperty"); onProperty.addAttribute("resource", "#TargetConcept"); restriction.addContent(onProperty); subClassOf.addContent(restriction); if (!r.getRegra().equals("HerTT")) { String cardinalidadeDireta = "(" + r.getCardDireta1(); String cardinalidadeInversa = "(" + r.getCardInversa1(); if (r.getCardDireta2() == -1) cardinalidadeDireta += ",N)"; else cardinalidadeDireta += "," + r.getCardDireta2() + ")"; if (r.getCardInversa2() == -1) cardinalidadeInversa += ",N)"; else cardinalidadeInversa += "," + r.getCardInversa2() + ")"; restriction = new Elemento("restriction"); restriction.addAttribute("hasValue", cardinalidadeDireta); onProperty = new Elemento("onProperty"); onProperty.addAttribute("resource", "#DirectCardinality"); restriction.addContent(onProperty); 78 if (cardinalidadeDireta.equals(cardinalidadeInversa)) { onProperty = new Elemento("onProperty"); onProperty.addAttribute("resource", "#InverseCardinality"); restriction.addContent(onProperty); subClassOf.addContent(restriction); } else { subClassOf.addContent(restriction); restriction = new Elemento("restriction"); restriction.addAttribute("hasValue", cardinalidadeInversa); onProperty = new Elemento("onProperty"); onProperty.addAttribute("resource", "#InverseCardinality"); restriction.addContent(onProperty); subClassOf.addContent(restriction); } } restriction = new Elemento("restriction"); onProperty = new Elemento("onProperty"); onProperty.addAttribute("resource", "#RelationshipMappings"); restriction.addContent(onProperty); InterfaceElemento toClass = new Elemento("toClass"); toClass.addAttribute("resource", "#" + r.getConceito1().getConceito() + r.getConceito2().getConceito() + nomeXSD); onProperty.addContent(toClass); subClassOf.addContent(restriction); relacaoOWL.addContent(subClassOf); root.addContent(relacaoOWL); } } private static LinkedList<LinkedList<Relacao>> pertenceADisjuncoes( Relacao r, LinkedList<LinkedList<Relacao>> disjuncoes) { LinkedList<LinkedList<Relacao>> resposta = new LinkedList<LinkedList<Relacao>>(); for (int i = 0; i < disjuncoes.size(); i++) for (int j = 0; j < disjuncoes.get(i).size(); j++) if (disjuncoes.get(i).get(j).equals(r)) resposta.add(disjuncoes.get(i)); return resposta; } } package controle; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.jdom.Document; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; 79 import ed.InterfaceElemento; /** * @author Leo * @version 1.5 * @created 28 de Novembro de 2005 */ public class Persistencia { FileOutputStream out; Document doc; String nomeArq; public Persistencia(String nome) { nomeArq = nome; doc = new Document(); try { out = new FileOutputStream(nome); } catch (FileNotFoundException e) { System.out.println("Impossivel a criação do arquivo " + nome); e.printStackTrace(); } } /** * Adiciona conteúdo para a geração de um arquivo de saída * * @param e * Elemento root do documento devidamente ligado aos seus * conteúdos (filhos, atributos...) */ public void addContent(InterfaceElemento e) { doc = e.getDocument(); } /** * Serializa o documento */ public void close() { XMLOutputter serializer = new XMLOutputter(Format.getPrettyFormat()); try { serializer.output(doc, out); out.flush(); out.close(); } catch (IOException e) { System.out.println("Erro na escrita do documento " + nomeArq); e.printStackTrace(); } } } package controle; import interfac.Interface; import java.util.HashSet; import java.util.LinkedList; import java.util.Set; 80 import subetapas.Conversao_Fase1; import subetapas.Conversao_Fase2; import subetapas.Conversao_Fase3; import subetapas.Conversao_Fase4; import subetapas.PreProcessamento_Fase1; import subetapas.PreProcessamento_Fase2; import subetapas.PreProcessamento_Fase3; import subetapas.PreProcessamento_Fase4; import subetapas.PreProcessamento_Fase5; import subetapas.Reestruturacao; import ed.InterfaceElemento; /** * @author Leo * @version 1.10 * @created 28 de Novembro de 2005 */ public class ProcessoMain { Evento e; Interface interfac; ConstrutorOWL construtor; AbstractEtapas etapaAtual; public ProcessoMain() { interfac = new Interface(); String nomeArq; LinkedList<String> nomeArqProcessado = interfac .intervencaoUsuarioEspecialista("", "Nome Arquivo", ""); System.out.println("Nome arquivo:"+nomeArqProcessado.get(0)); construtor = new ConstrutorOWL(interfac, nomeArqProcessado.get(0) .substring(0, nomeArqProcessado.get(0).length() - 4)); Set<AbstractObserver> observadores = new HashSet<AbstractObserver>(); observadores.add(construtor); try { etapaAtual = new PreProcessamento_Fase1(interfac, observadores); e = new Evento(this); e.abrirArquivo(nomeArqProcessado.get(0), etapaAtual.qualArquivoSaida()); nomeArq = etapaAtual.qualArquivoSaida(); etapaAtual = new PreProcessamento_Fase2(interfac, observadores); e.abrirArquivo(nomeArq, etapaAtual.qualArquivoSaida()); nomeArq = etapaAtual.qualArquivoSaida(); etapaAtual = new PreProcessamento_Fase3(interfac, observadores); e.abrirArquivo(nomeArq, etapaAtual.qualArquivoSaida()); nomeArq = etapaAtual.qualArquivoSaida(); etapaAtual = new PreProcessamento_Fase4(interfac, observadores); e.abrirArquivo(nomeArq, etapaAtual.qualArquivoSaida()); nomeArq = etapaAtual.qualArquivoSaida(); etapaAtual = new PreProcessamento_Fase5(interfac, observadores); 81 e.abrirArquivo(nomeArq, etapaAtual.qualArquivoSaida()); nomeArq = etapaAtual.qualArquivoSaida(); etapaAtual = new Conversao_Fase1(interfac, observadores); e.abrirArquivo(nomeArq, etapaAtual.qualArquivoSaida()); nomeArq = etapaAtual.qualArquivoSaida(); etapaAtual = new Conversao_Fase2(interfac, observadores); e.abrirArquivo(nomeArq, etapaAtual.qualArquivoSaida()); nomeArq = etapaAtual.qualArquivoSaida(); etapaAtual = new Conversao_Fase3(interfac, observadores); e.abrirArquivo(nomeArq, etapaAtual.qualArquivoSaida()); nomeArq = etapaAtual.qualArquivoSaida(); etapaAtual = new Conversao_Fase4(interfac, observadores); e.abrirArquivo(nomeArq, etapaAtual.qualArquivoSaida()); nomeArq = etapaAtual.qualArquivoSaida(); etapaAtual = new Reestruturacao(interfac, observadores); e.abrirArquivo(nomeArq, etapaAtual.qualArquivoSaida()); } catch (Throwable thr) { interfac .recebaInformacoes("O programa executou um erro fatal e será cancelado! " + thr.getLocalizedMessage()); thr.printStackTrace(); System.exit(1); } } /** * De acordo com a etapa em voga no sistema, tal classe encaminha o elemento * gerado para a devida subEtapa * * @param elem * Elemento criado para ser processado */ public void trateElemento(InterfaceElemento elem) { etapaAtual.trateElemento(elem); } public static void main(String[] args) { new ProcessoMain(); } } B.3 - PERSISTÊNCIA package persistencia; import java.sql.DriverManager; import java.sql.SQLException; import com.mysql.jdbc.ResultSet; import com.mysql.jdbc.Statement; public class Conexao { java.sql.Connection connection = null; /** * @param args */ 82 public Conexao() { try { //String driverName = "sun.jdbc.odbc.JdbcOdbcDriver"; String driverName = "com.mysql.jdbc.Driver"; Class.forName(driverName); System.out.println("Load class"); // Criando a conexão com o Banco de Dados String servidor = "localhost:3306"; String nomeDoBanco = "catalogos"; String url = "jdbc:mysql://" + servidor + "/" + nomeDoBanco; // a JDBC url String login = "root"; String senha = "admin"; System.out.println("Url: " + url); connection = DriverManager.getConnection(url, login, senha); System.out.println("connection"); } catch (ClassNotFoundException e) { //Driver não encontrado System.out.println("O driver expecificado não foi encontrado."); } catch (SQLException e) { System.out.println("Não foi possível conectar ao Banco de Dados"); } } public ResultSet executeSql(String sql){ Statement stmp; try { stmp = (Statement) connection.createStatement(); return (ResultSet) stmp.executeQuery(sql); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } public void executeInsertOrUpdate(String sql){ Statement stmp; try { stmp = (Statement) connection.createStatement(); stmp.executeUpdate(sql); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } 83 } public void close(){ try { connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } B.4 - DAO package dao; import persistencia.Conexao; import bean.ElementosRenomeados; import com.mysql.jdbc.ResultSet; public class ElementoRenomeadoDAO { public void insere(ElementosRenomeados e){ //abre conexao Conexao db = new Conexao(); //faz oper String sql = "insert into elementos_renomeados (fonte, nome_renomeado, nome_original) values ("+e.getFonte()+","+e.getNomeRenomeado()+","+e.getNomeOriginal()+")"; db.executeInsertOrUpdate(sql); //fecha conexao db.close(); } public ElementosRenomeados findById(int id){ //abre conexao Conexao db = new Conexao(); ElementosRenomeados e = null; //faz oper String sql = "Select * from elementos_renomeados er where er.id = " + id ; ResultSet rs = db.executeSql(sql); /* if (rs!=null) { List<ElementosRemovidos> l = new ArrayList<ElementosRemovidos>(rs.); if (!l.isEmpty()) { e = l.get(0); } }*/ //fecha conexao 84 db.close(); return e; } } package dao; import java.util.ArrayList; import java.util.List; import persistencia.Conexao; import com.mysql.jdbc.ResultSet; import bean.ElementosRemovidos; public class ElementosRemovidosDAO { public void insere(ElementosRemovidos e){ //abre conexao Conexao db = new Conexao(); //faz oper String sql = "insert into elementos_removidos (fonte, elemento_removido, elemento_pai, elemento_filho) values ("+e.getFonte()+","+e.getElementoRemovido()+","+e.getElementoPai()+"," +e.getElementoFilho()+")"; db.executeInsertOrUpdate(sql); //fecha conexao db.close(); } public ElementosRemovidos findById(int id){ //abre conexao Conexao db = new Conexao(); ElementosRemovidos e = null; //faz oper String sql = "Select * from elementos_removidos er where er.id = " + id ; ResultSet rs = db.executeSql(sql); /* if (rs!=null) { List<ElementosRemovidos> l = new ArrayList<ElementosRemovidos>(rs.); if (!l.isEmpty()) { e = l.get(0); } }*/ //fecha conexao db.close(); return e; } } package dao; import java.util.ArrayList; import java.util.List; import persistencia.Conexao; import com.mysql.jdbc.ResultSet; import bean.ElementosVirtuais; 85 public class ElementosVirtuaisDAO { public void insere(ElementosVirtuais e){ //abre conexao Conexao db = new Conexao(); //faz oper String sql = "insert into elementos_virtuais (fonte, elemento_virtual) values ("+e.getFonte()+","+e.getElementoVirtual()+")"; db.executeInsertOrUpdate(sql); //fecha conexao db.close(); } public ElementosVirtuais findById(int id){ //abre conexao Conexao db = new Conexao(); ElementosVirtuais e = null; //faz oper String sql = "Select * from elementos_virtuais er where er.id = " + id ; ResultSet rs = db.executeSql(sql); /* if (rs!=null) { List<ElementosRemovidos> l = new ArrayList<ElementosRemovidos>(rs.); if (!l.isEmpty()) { e = l.get(0); } }*/ //fecha conexao db.close(); return e; } } B.5 - ED package ed; import java.util.LinkedList; /** * @author Leo * @version 1.3 * @created 28 de Novembro de 2005 */ public class Conceito extends MudancaElemento { String regra; String conceito; boolean ehLexico; LinkedList<String> anotacoes; public Conceito(String con) { conceito = con; 86 anotacoes = new LinkedList<String>(); } public Conceito(String r, String conc, boolean lexico) { regra = r; conceito = conc; ehLexico = lexico; anotacoes = new LinkedList<String>(); } public Conceito(String r, String conc, boolean lexico, LinkedList<String> anot) { regra = r; conceito = conc; ehLexico = lexico; anotacoes = anot; } /* * (non-Javadoc) * * @see ed.MudancaElemento#getConceito() */ public String getConceito() { return conceito; } /** * Este método caracteriza o elemento como léxico * * @return booleano true - é léxico - e false - não é léxico */ public boolean ehLexico() { return ehLexico; } /* * (non-Javadoc) * * @see ed.MudancaElemento#getAnotacoes() */ public LinkedList<String> getAnotacoes() { return anotacoes; } /* * (non-Javadoc) * * @see ed.MudancaElemento#getRegra() */ public String getRegra() { return regra; } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object o) { if (!o.getClass().getSimpleName().equals("Conceito")) return false; else if (!this.conceito.equals(((Conceito) o).getConceito())) return false; 87 else if (PreDefinicoes.ehTipoPreDefinido(this.conceito)) if (!this.anotacoes.equals(((Conceito) o).getAnotacoes())) return false; return true; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ public String toString() { return "Conceito\nRegra =\"" + regra + "\" Conceito =\"" + conceito + "\" Lexico =\"" + ehLexico + "\"\n"; } /* * (non-Javadoc) * * @see java.lang.Object#clone() */ @Override public MudancaElemento clone() { return new Conceito(regra, conceito, ehLexico, anotacoes); } } package ed; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.jdom.Document; import org.jdom.Element; import org.jdom.Namespace; /** * @author Leo * @version 1.14 * @created 28 de Novembro de 2005 */ public class Elemento implements InterfaceElemento { Element elem; public Elemento() { elem = null; } public Elemento(Element e) { elem = e; } public Elemento(String name) { elem = new Element(name); } public Elemento(String name, Namespace space) { elem = new Element(name, space); } 88 /* * (non-Javadoc) * * @see ed.InterfaceElemento#getAttributeValue(java.lang.String) */ public java.lang.String getAttributeValue(java.lang.String name) { return elem.getAttributeValue(name); } /* * (non-Javadoc) * * @see ed.InterfaceElemento#getName() */ public java.lang.String getName() { return elem.getName(); } /* * (non-Javadoc) * * @see ed.InterfaceElemento#getChildren() */ @SuppressWarnings("unchecked") public List getChildren() { List retorno = new LinkedList<Elemento>(); List filhos = elem.getChildren(); Iterator iterator = filhos.iterator(); while (iterator.hasNext()) { Element elem = (Element) iterator.next(); retorno.add(new Elemento(elem)); } return retorno; } /* * (non-Javadoc) * * @see ed.InterfaceElemento#addContent(ed.InterfaceElemento) */ public void addContent(InterfaceElemento incluir) { elem.addContent(((Elemento) incluir).getElement()); } /* * (non-Javadoc) * * @see ed.InterfaceElemento#addAttribute(java.lang.String, * java.lang.String) */ public void addAttribute(String nome, String value) { elem.setAttribute(nome, value); } public Document getDocument() { return (Document) elem.getDocument(); } /* * (non-Javadoc) * * @see java.lang.Object#clone() */ public Elemento clone() { return new Elemento((Element) elem.clone()); } /* * (non-Javadoc) * * @see ed.InterfaceElemento#removeChildren(ed.InterfaceElemento) 89 */ public void removeChildren(InterfaceElemento e) { while (elem.removeContent(((Elemento) e).getElement())) ; } /* * (non-Javadoc) * * @see ed.InterfaceElemento#caminhoDOM() */ public String caminhoDOM() { String retorno = "/" + this.getQualifiedName(); List atributos = this.getAttributes(); String at; boolean primeiraVez = true; for (Object attr : atributos) { at = attr.toString(); at = at.substring(1, at.length() - 1); at = at.replace("Attribute:", ""); if (at.matches("[^/]*")) { if (primeiraVez) { retorno += "->"; retorno += at; primeiraVez = false; } else retorno += "," + at; } } String montagem; Element principio = elem; while (!(principio.getParent() instanceof Document)) { principio = principio.getParentElement(); atributos = principio.getAttributes(); primeiraVez = true; montagem = "/" + principio.getQualifiedName(); for (Object attr : atributos) { at = attr.toString(); at = at.substring(1, at.length() - 1); at = at.replace("Attribute:", ""); if (at.matches("[^/]*")) { if (primeiraVez) { montagem += "->"; montagem += at; primeiraVez = false; } else montagem += "," + at; } } retorno = montagem + retorno; } return retorno; } /* * (non-Javadoc) * 90 * @see ed.InterfaceElemento#getParentElement() */ public Elemento getParentElement() { return new Elemento(elem.getParentElement()); } /* * (non-Javadoc) * * @see ed.InterfaceElemento#getQualifiedName() */ public String getQualifiedName() { return elem.getQualifiedName(); } /* * (non-Javadoc) * * @see ed.InterfaceElemento#removeChildren(java.lang.String) */ public boolean removeChildren(String name) { return elem.removeChild(name); } /* * (non-Javadoc) * * @see ed.InterfaceElemento#getNamespace(java.lang.String) */ public Namespace getNamespace(String prefix) { return elem.getNamespace(prefix); } /* * (non-Javadoc) * * @see ed.InterfaceElemento#setName(java.lang.String) */ public void setName(String nome) { elem.setName(nome); } public void setNameSpace(Namespace nome) { elem.setNamespace(nome); } /* * (non-Javadoc) * * @see ed.InterfaceElemento#getTipoElementoSimples() */ public String getTipoElementoSimples() { if (elem.getAttributeValue("type") != null) return elem.getAttributeValue("type"); List f = this.getChildren(); Iterator iterator = f.iterator(); String nomeDerivacao = ""; while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); nomeDerivacao = "" + elemFilho.getTipoElementoSimples(); } if (elem.getName().equals("restriction")) if (elem.getAttributeValue("base") != null) return elem.getAttributeValue("base"); if (elem.getName().equals("list")) return "list"; if (elem.getName().equals("union")) return "union"; return nomeDerivacao; } 91 /* * (non-Javadoc) * * @see ed.InterfaceElemento#getInformacoesPreDefinidas() */ public LinkedList<String> getInformacoesPreDefinidas() { LinkedList<String> resposta = new LinkedList<String>(); resposta.add("tipo=" + this.getTipoElementoSimples()); if (!this.ehComplexo()) { LinkedList<String> aux = this.getEnumeracoes(); if (aux.size() > 0) resposta.add("enumeracao=" + aux); } return resposta; } private LinkedList<String> getEnumeracoes() { List f = this.getChildren(); Iterator iterator = f.iterator(); LinkedList<String> resposta = new LinkedList<String>(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (!(elemFilho.getName().equals("element") && !elemFilho.ehVazio())) resposta.addAll(elemFilho.getEnumeracoes()); } if (this.getName().equals("enumeration")) resposta.add(elem.getAttributeValue("value")); return resposta; } /* * (non-Javadoc) * * @see ed.InterfaceElemento#ehComplexo() */ public boolean ehComplexo() { if (elem.getAttributeValue("type") != null) if (!PreDefinicoes .ehTipoPreDefinido(elem.getAttributeValue("type"))) return true; else return false; return this.ehElemComplexo(); } private boolean ehElemComplexo() { List f = this.getChildren(); Iterator iterator = f.iterator(); boolean resposta = false; while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); resposta = resposta || elemFilho.ehComplexo(); } 92 if (elem.getName().equals("complexType")) resposta = true; return resposta; } /* * (non-Javadoc) * * @see ed.InterfaceElemento#ehVazio() */ public boolean ehVazio() { List f = this.getChildren(); Iterator iterator = f.iterator(); boolean resposta = false; while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); resposta = resposta || (!elemFilho.temElementosDecalarados()); } return resposta; } private boolean temElementosDecalarados() { List f = this.getChildren(); Iterator iterator = f.iterator(); boolean resposta = false; while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); resposta = resposta || elemFilho.temElementosDecalarados(); } if (this.getName().equals("element")) return true; return resposta; } /* * (non-Javadoc) * * @see ed.InterfaceElemento#setTag(java.lang.String, java.lang.String) */ public void setTag(String tag, String value) { this.addAttribute(tag, value); } /* * (non-Javadoc) * * @see ed.InterfaceElemento#getTag(java.lang.String) */ public String getTag(String tag) { return this.getAttributeValue(tag); } /* * (non-Javadoc) * 93 * @see ed.InterfaceElemento#getAttributes() */ public List getAttributes() { return elem.getAttributes(); } /* * (non-Javadoc) * * @see ed.InterfaceElemento#possuiElementosIrmaosIguais() */ public boolean possuiElementosIrmaosIguais() { List f = this.getParentElement().getChildren(); Iterator iterator = f.iterator(); int qtosFilhosIguais = -1; while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (elemFilho.getName().equals(elem.getName())) if (elemFilho.getAttributeValue("name") != null && elem.getAttributeValue("name") != null) { if (elemFilho.getAttributeValue("name").equalsIgnoreCase( elem.getAttributeValue("name"))) qtosFilhosIguais++; } else if (elemFilho.getAttributeValue("name") == null && elem.getAttributeValue("name") == null) qtosFilhosIguais++; } if (qtosFilhosIguais > 0) return true; else return false; } /* * (non-Javadoc) * * @see ed.InterfaceElemento#apliqueCardD() */ public LinkedList<Integer> apliqueCardD() { LinkedList<Integer> resposta = new LinkedList<Integer>(); int cardD1 = Integer.MIN_VALUE; int cardD2 = Integer.MAX_VALUE; if (this.getParentElement().getAttributeValue("minOccurs") != null) if (this.getParentElement().getAttributeValue("minOccurs").equals( "unbounded")) cardD1 = -1; else cardD1 = Integer.parseInt(this.getParentElement() .getAttributeValue("minOccurs")); if (this.getParentElement().getAttributeValue("maxOccurs") != null) 94 if (this.getParentElement().getAttributeValue("maxOccurs").equals( "unbounded")) cardD2 = -1; else cardD2 = Integer.parseInt(this.getParentElement() .getAttributeValue("maxOccurs")); if (cardD1 == Integer.MIN_VALUE) if (elem.getAttributeValue("minOccurs") == null) cardD1 = 1; else if (elem.getAttributeValue("minOccurs").equals("unbounded")) cardD1 = -1; else cardD1 = Integer.parseInt(elem.getAttributeValue("minOccurs")); if (cardD2 == Integer.MAX_VALUE) if (elem.getAttributeValue("maxOccurs") == null) cardD2 = 1; else if (elem.getAttributeValue("maxOccurs").equals("unbounded")) cardD2 = -1; else cardD2 = Integer.parseInt(elem.getAttributeValue("maxOccurs")); resposta.addLast(cardD1); resposta.addLast(cardD2); return resposta; } /* * (non-Javadoc) * * @see ed.InterfaceElemento#apliqueCardR(java.lang.String) */ public LinkedList<Integer> apliqueCardR(String grupo) { int cardD1 = 0; int cardD2 = 0; LinkedList<Integer> resposta = new LinkedList<Integer>(); if (elem.getAttributeValue("name") != null) { List f = this.getParentElement().getChildren(); Iterator iterator = f.iterator(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (elemFilho.getAttributeValue("name") != null) if (elemFilho.getAttributeValue("name").equals( elem.getAttributeValue("name"))) if ((elemFilho.getTag("grupo") == null && this .getTag("grupo") == null) || (this.getTag("grupo") != null && elemFilho.getTag("grupo") != null && this .getTag("grupo").equals( 95 elemFilho.getTag("grupo")))) { if (elemFilho.getAttributeValue("minOccurs") == null) cardD1++; else cardD1 += Integer.parseInt(elemFilho .getAttributeValue("minOccurs")); if (cardD2 != -1) // jah estah setada em 'N' if (elemFilho.getAttributeValue("maxOccurs") == null) cardD2++; else if (elemFilho.getAttributeValue( "maxOccurs").equals("unbounded")) cardD2 = -1; else cardD2 += Integer.parseInt(elemFilho .getAttributeValue("maxOccurs")); } } } resposta.addLast(cardD1); resposta.addLast(cardD2); return resposta; } public Element getElement() { return elem; } } package ed; import java.util.LinkedList; import java.util.List; import org.jdom.Document; import org.jdom.Element; import org.jdom.Namespace; /** * @author Leo * @version 1.9 * @created 28 de Novembro de 2005 */ public interface InterfaceElemento { /** * @param nome * Nome do atributo * @return String String com o valor contido no atributo passado como * paramentro 96 */ public abstract java.lang.String getAttributeValue(java.lang.String name); /** * Retorna nome do elemento * * @return String Nome */ public abstract java.lang.String getName(); /** * Lista com todos os elementos que são filhos (apenas os de grau 1) do * elemento em questão * * @return List */ public abstract java.util.List getChildren(); /** * Adiciona o elemento passado como parâmetro na lista de filhos do elemento * em questão. * * @param child * Elemento para adição */ public abstract void addContent(InterfaceElemento child); /** * Adiciona o atributo passado como parâmetro na lista de atributos do * elemento em questão * * @param nome * nome do atributo a ser adicionado * @param value * Valor do atributo nomeado no parâmetro nome */ public abstract void addAttribute(String nome, String value); public abstract Document getDocument(); /** * Clone do elemento em questão * * @return clone */ public abstract Elemento clone(); /** * Remove do elemento em questão todos os filhos que possuem as mesmas * características do elemento passado como parâmetro * * @param e * Elemento para comparação 97 */ public abstract void removeChildren(InterfaceElemento e); /** * Remove do elemento em questão todos os elementos que possuem nome igual * ao passado como parâmetro * * @param name * Nome do elemento para comparação * @return */ public abstract boolean removeChildren(String name); /** * Retorna String baseada em XPath da expressão que corresponde ao caminho * DOM do elemento em questão. O caminho é baseada em: * /namespace:elementName->elementAtt * * @return String Caminho DOM do elemento */ public abstract String caminhoDOM(); /** * Pega o elemento imediatamente superior ao elemento em questão * * @return Elemento Elemento pai */ public abstract Elemento getParentElement(); /** * Retorna o nome do elemento junto com seu respectivo namespace no padrão * "namespace:elementName" * * @return String Nome completo do elemento */ public abstract java.lang.String getQualifiedName(); public abstract Namespace getNamespace(java.lang.String prefix); /** * Troca o nome do elemento em questão com o passado como parâmetro * * @param name * Novo nome do elemento */ public abstract void setName(java.lang.String name); public abstract void setNameSpace(Namespace namespace); /** * Retorna o tipo do elemento passado como parâmetro, desde que este seja 98 * simples (tipos pré-definidos) * * @return String Tipo do elemento declarado */ public abstract String getTipoElementoSimples(); /** * Coleta informações de tipo, enumerações e restrição dos elementos * declarados * * @return LinkedList Lista com informações divididas */ public abstract LinkedList<String> getInformacoesPreDefinidas(); /** * Este método caracteriza o elemento como complexo * * @return booleano true - é complexo - e false - não é complexo */ public abstract boolean ehComplexo(); /** * Este método caracteriza o elemento como vazio * * @return booleano true - é vazio - e false - não é vazio */ public abstract boolean ehVazio(); /** * Adiciona informações aos elementos (como atributos) * * @param tag * Nome da tag adicionada * @param value * Valor que se deseja adicionar na tag */ public abstract void setTag(String tag, String value); /** * Retorna o valor da tag passada como parâmetro * * @param tag * String do nome da tag do elemento * @return */ public abstract String getTag(String tag); public abstract List getAttributes(); /** * Retorna um booleano dizendo se existem elementos com o mesmo nome * declarado no mesmo nível do elemento em questão (repetições) * * @return booleano true - existem irmãos iguais - e false - não existem * irmãos iguais - 99 */ public abstract boolean possuiElementosIrmaosIguais(); /** * Aplica a regra de cardinalidade definida no trabalho de Arthur Frantz * (2004) * * @return LinkesList Lista com informações de aplicação desta regra */ public abstract LinkedList<Integer> apliqueCardD(); /** * Aplica a regra de cardinalidade definida no trabalho de Arthur Frantz * (2004) * * @return LinkesList Lista com informações de aplicação desta regra */ public abstract LinkedList<Integer> apliqueCardR(String grupo); public abstract Element getElement(); } package ed; import java.util.LinkedList; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public abstract class MudancaElemento { /** * Retorna o nome do Conceito associada a mudança em questão. No caso de * relacionamentos retorna o nome do primeiro conceito de uma relação * * @return String Nome do conceito principal da mudança */ public abstract String getConceito(); /** * Retorna o nome da regra que originou essa mudança * * @return String Nome da regra originadora da mudança */ public abstract String getRegra(); /** * Retorna informações significativas da mudança em questão: restrições, 100 * enumerações, etc... * * @return LinkedList Lista com informações relevantes a mudança */ public abstract LinkedList<String> getAnotacoes(); /* * (non-Javadoc) * * @see java.lang.Object#toString() */ public abstract String toString(); /* * (non-Javadoc) * * @see java.lang.Object#clone() */ public abstract MudancaElemento clone(); } package ed; /** * @author Leo * @version 1.4 * @created 28 de Novembro de 2005 */ public class PreDefinicoes { private static String[] listaPreDenifida = { "integer", "string", "list", "union" }; private static String[] listaTagAdicional = { "qualificacao", "grupo" }; /** * Método que caracteriza o tipo passado como pré-definido na linguagem XSD * * @param tipoElementoSimples * String do tipo para ser analisado * @return */ public static boolean ehTipoPreDefinido(String tipoElementoSimples) { for (int i = 0; i < listaPreDenifida.length; i++) if (tipoElementoSimples.matches(".*" + listaPreDenifida[i])) return true; return false; } /** * Caracteriza uma informação como adicional a modelagem criada pelo finte * XSD * * @param tag * String representativa do nome do conteúdo para ser * classificado 101 * @return */ public static boolean ehTagAdicional(String tag) { for (int i = 0; i < listaTagAdicional.length; i++) if (tag.matches(".*" + listaTagAdicional[i])) return true; return false; } /** * Realiza uma igualdade de caminhos DOM's mais inteligente. Atributos não * precisam necessariamente estar presetes no caminho de checagem. Porém, * quando estiverem, serão levados em consideração * * @param caminho1 * String representativa do caminho DOM original * @param caminho2 * String representativa do caminho DOM que quer ser comparado * @return */ public static boolean osCaminhosDomSaoIguais(String caminho1, String caminho2) { String[] caminho1Split = caminho1.split("/"); String[] caminho2Split = caminho2.split("/"); if (caminho1Split.length != caminho2Split.length) return false; else { for (int i = 1; i < caminho1Split.length; i++) { caminho2Split[i] = caminho2Split[i] + ".*"; caminho2Split[i] = caminho2Split[i].replace("->", ">.*"); if (!caminho1Split[i].matches(caminho2Split[i])) return false; } } return true; } } package ed; import java.util.LinkedList; /** * @author Leo * @version 1.5 * @created 28 de Novembro de 2005 */ public class Relacao extends MudancaElemento { String regra; Conceito conceito1; Conceito conceito2; int cardDireta1; int cardDireta2; 102 int cardInversa1; int cardInversa2; public Relacao(String r, String conc, Conceito conc2, int cd1, int cd2, int ci1, int ci2) { regra = r; conceito1 = new Conceito(conc); conceito2 = conc2; cardDireta1 = cd1; cardDireta2 = cd2; cardInversa1 = ci1; cardInversa2 = ci2; } public Relacao(String r, String conc, String conc2, int cd1, int cd2, int ci1, int ci2) { regra = r; conceito1 = new Conceito(conc); conceito2 = new Conceito(conc2); cardDireta1 = cd1; cardDireta2 = cd2; cardInversa1 = ci1; cardInversa2 = ci2; } public Relacao(String r, Conceito conc, Conceito conc2, int cd1, int cd2, int ci1, int ci2) { regra = r; conceito1 = conc; conceito2 = conc2; cardDireta1 = cd1; cardDireta2 = cd2; cardInversa1 = ci1; cardInversa2 = ci2; } /** * Retorna o primeiro número do par representativo da cardinalidade direta * (x,y) * * @return int Primeiro número do par da CardD */ public int getCardDireta1() { return cardDireta1; } /** * Retorna o segundo número do par representativo da cardinalidade direta * (x,y) * * @return int Segundo número do par da CardD */ 103 public int getCardDireta2() { return cardDireta2; } /** * Retorna o primeiro número do par representativo da cardinalidade inversa * (x,y) * * @return int Primeiro número do par da CardI */ public int getCardInversa1() { return cardInversa1; } /** * Retorna o segundo número do par representativo da cardinalidade inversa * (x,y) * * @return int Segundo número do par da CardI */ public int getCardInversa2() { return cardInversa2; } /** * Retorna a primeira instância Conceito que faz parte desta relação * * @return Conceito Instância que compõe a relação */ public Conceito getConceito1() { return conceito1; } /** * Retorna a segunda instância Conceito que faz parte desta relação * * @return Conceito Instância que compõe a relação */ public Conceito getConceito2() { return conceito2; } /* * (non-Javadoc) * * @see ed.MudancaElemento#getRegra() */ public String getRegra() { return regra; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ public String toString() { return "Relação\nRegra =\"" + regra + "\" Conceito 1 =\"" + conceito1.getConceito() + "\" Conceito 2 =\"" + conceito2.getConceito() + "\"" + " CardD1 =" + cardDireta1 + " CardD2 =" + cardDireta2 + " CardI1 =" + cardInversa1 + " CardI2 =" + cardInversa2 + "\n"; } 104 /* * (non-Javadoc) * * @see ed.MudancaElemento#getConceito() */ @Override public String getConceito() { return conceito1.getConceito(); } /* * (non-Javadoc) * * @see java.lang.Object#clone() */ @Override public MudancaElemento clone() { return new Relacao(regra, conceito1.getConceito(), conceito2, cardDireta1, cardDireta2, cardInversa1, cardInversa2); } /* * (non-Javadoc) * * @see ed.MudancaElemento#getAnotacoes() */ @Override public LinkedList<String> getAnotacoes() { return null; } } B.6 - INTERFAC package interfac; import java.util.LinkedList; import controle.AbstractObserver; /** * @author Leo * @version 1.1 * @created 28 de Novembro de 2005 */ public abstract class AbstractInterface extends AbstractObserver { /** * Método para notificação de mensagens não significativas para o * funcionamento do programa * * @param mensagem * Mensagem que se quer notificar a interface */ public abstract void recebaInformacoes(String mensagem); 105 /** * Método para interação com o usuário especialista. Todas as informações * necessárias para a tomada de decisão estão presentes: a regra que deseja * interagir, qual o assunto da interação e quais elementos são atingidos * * @param regra * Nome da regra que deseja a interação * @param oQue * A causa da interação * @param elemento * Quais elementos são atingidos com tal interação * @return Resposta dependente do usuário especialista */ public abstract LinkedList<String> intervencaoUsuarioEspecialista( String regra, String oQue, String elemento); } package interfac; import java.util.LinkedList; /** * @author Leo * @version 1.12 * @created 28 de Novembro de 2005 */ public class Interface extends AbstractInterface { LinkedList<String> resposta; @Override protected void update() { mudanca = assunto.get(); // faz consistencia na interface } /* * (non-Javadoc) * * @see interfac.AbstractInterface#recebaInformacoes(java.lang.String) */ public void recebaInformacoes(String mensagem) { System.out.println("*****"); System.out.println("Recebida a Informacao pela Interface = " + mensagem); System.out.println("*****\n"); } 106 /* * (non-Javadoc) * * @see interfac.AbstractInterface #intervencaoUsuarioEspecialista(java.lang.String, * java.lang.String, java.lang.String) */ public LinkedList<String> intervencaoUsuarioEspecialista(String regra, String oQue, String elemento) { resposta = new LinkedList<String>(); if (oQue.equals("Nome Arquivo")) resposta.addLast("xsdTeste.xsd"); if (regra.equals("RET") && oQue.equals("Remocao Elementos")) { resposta .addLast("/xs:schema/xs:element/xs:complexType/xs:sequence/xs:element>name=\"issues\""); resposta .addLast("/xs:schema/xs:complexType/xs:sequence/xs:element>name=\"articles\""); resposta .addLast("/xs:schema/xs:complexType/xs:sequence/xs:element>name=\"authors\""); } if (regra.equals("EC") && oQue.equals("Qualificação")) resposta.addLast("sim"); if (regra.equals("RMC") && oQue.equals("Qualificação")) resposta.addLast("sim"); if (regra.equals("AT") && oQue.equals("CardR")) resposta.addLast("default"); if (regra.equals("ATAny") && oQue.equals("CardR")) resposta.addLast("default"); if (regra.equals("Q") && oQue.equals("CardR")) resposta.addLast("default"); if (regra.equals("RMC") && oQue.equals("CardR")) { resposta.addLast("1"); resposta.addLast("2"); } if (regra.equals("RREF") && oQue.equals("Semântica")) resposta.addLast("possui"); if (regra.equals("Q") && oQue.equals("Qualificação")) if (elemento.matches(".*name=\"Leo\".*")) resposta.addLast("sim"); else resposta.addLast("nao"); if (regra.equals("RER") && oQue.equals("Classificação")) resposta.addLast("grupoX"); 107 return resposta; } } package interfac; import java.util.LinkedList; public class Interface2 extends AbstractInterface { LinkedList<String> resposta; @Override protected void update() { mudanca = assunto.get(); // faz consistencia na interface } public void recebaInformacoes(String mensagem) { System.out.println("*****"); System.out .println("Recebida a Informacao pela Interface = " + mensagem); System.out.println("*****\n"); } public LinkedList<String> intervencaoUsuarioEspecialista(String regra, String oQue, String elemento) { resposta = new LinkedList<String>(); if (oQue.equals("Nome Arquivo")) resposta.addLast("main.xsd"); if (regra.equals("RET") && oQue.equals("Remocao Elementos")) { resposta .addLast("/xs:schema/xs:attribute/xs:simpleType/xs:restriction"); } if (regra.equals("REA")) { resposta .addLast("/xs:schema/xs:sequence/xs:element>name=\"Seq1\""); resposta.addLast("Sequencia1"); resposta .addLast("/xs:schema/xs:sequence/xs:element>name=\"Seq2\""); resposta.addLast("Sequencia2"); resposta.addLast("/xs:schema/xs:sequence/xs:element"); resposta.addLast("xs:element"); resposta .addLast("/xs:schema/xs:sequence/xs:element>name=\"Seq3\""); 108 resposta.addLast("Sequencia3"); resposta .addLast("/xs:schema/xs:complexType/xs:choice/xs:element>name=\"TenderecoOp1\""); resposta.addLast("EnderecoComComplemento"); resposta .addLast("/xs:schema/xs:complexType/xs:choice/xs:element>name=\"TenderecoOp2\""); resposta.addLast("EnderecoSemComplemento"); } if (regra.equals("EC") && oQue.equals("Qualificação")) resposta.addLast("não"); if (regra.equals("RMC") && oQue.equals("Qualificação")) resposta.addLast("não"); if (regra.equals("AT") && oQue.equals("CardR")) resposta.addLast("default"); if (regra.equals("ATAny") && oQue.equals("CardR")) resposta.addLast("default"); if (regra.equals("Q") && oQue.equals("CardR")) resposta.addLast("default"); if (regra.equals("RMC") && oQue.equals("CardR")) { resposta.addLast("1"); resposta.addLast("2"); } if (regra.equals("RREF") && oQue.equals("Semântica")) resposta.addLast("possui"); if (regra.equals("Q") && oQue.equals("Qualificação")) resposta.addLast("não"); if (regra.equals("RER") && oQue.equals("Classificação")) resposta.addLast("grupoX"); if (regra.equals("RList") && oQue.equals("CardR")) { resposta.addLast("1"); resposta.addLast("2"); } if (regra.equals("RER") && oQue.equals("CardR")) { resposta.addLast("1"); resposta.addLast("2"); } if (regra.equals("RUnion") && oQue.equals("CardR")) { resposta.addLast("1"); resposta.addLast("2"); } if (regra.equals("ATAny") && oQue.equals("Relação")) { resposta.addLast("1"); resposta.addLast("2"); } if (regra.equals("RREF") && oQue.equals("CardR")) { resposta.addLast("1"); resposta.addLast("2"); } if (regra.equals("RAny") && oQue.equals("CardR")) { resposta.addLast("1"); resposta.addLast("2"); } return resposta; } 109 } B.7 - MODELO package modelo; import java.io.IOException; import java.util.Iterator; import java.util.List; import org.jdom.Document; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import controle.Evento; import ed.Elemento; import ed.InterfaceElemento; /** * @author Leo * @version 1.9 * @created 28 de Novembro de 2005 */ public class DOMReader implements InterfaceReader { String arqAntigo; Document doc; public DOMReader() { arqAntigo = ""; doc = null; } /* * (non-Javadoc) * * @see modelo.InterfaceReader#makeData(java.lang.String, java.lang.String, * controle.Evento) */ public void makeData(String fileAbrir, String fileGerado, Evento event) throws JDOMException, IOException { if (!fileAbrir.equals(arqAntigo)) { SAXBuilder builder = new SAXBuilder(); doc = builder.build(fileAbrir); } Elemento root = new Elemento(doc.getRootElement()); this.percorreArvore((InterfaceElemento) root, event); 110 event.recebeElemento(new Elemento("exit")); arqAntigo = fileGerado; } private void percorreArvore(InterfaceElemento root, Evento event) { event.recebeElemento(root); List children = root.getChildren(); Iterator iterator = children.iterator(); while (iterator.hasNext()) { Elemento elem = (Elemento) iterator.next(); this.percorreArvore(elem, event); } } } package modelo; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; import controle.Evento; import ed.Elemento; import ed.InterfaceElemento; /** * @author Leo * @version 1.4 * @created 28 de Novembro de 2005 */ public class DOMWriter implements InterfaceWriter { XMLOutputter xmlOut; OutputStream out; EventoInterno eventoI; InterfaceElemento root; public DOMWriter(String nomeArq) throws Throwable { root = null; eventoI = new EventoInterno(this); xmlOut = new XMLOutputter(Format.getPrettyFormat()); FileWriter file = new FileWriter(nomeArq); file 111 .append("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\" xmlns:daml=\"http://www.w3.org/2001/10/daml+oil#\">"); file.append("</rdf:RDF>"); file.close(); eventoI.abrirArquivo(nomeArq, ""); out = new FileOutputStream(new File(nomeArq)); } /* * (non-Javadoc) * * @see modelo.InterfaceWriter#output(ed.InterfaceElemento) */ public void output(InterfaceElemento element) throws IOException { xmlOut.output(((Elemento) element).getElement(), out); } protected void trateElementosExternos(InterfaceElemento elem) { if (elem.getName().equals("RDF")) root = elem; } /** * Retorna o elemento root (no caso o elemento <RSD>) para que se construa a * árvore XML para serialização * * @return InterfaceElemento Elemento root do documento de saída */ public InterfaceElemento getRoot() { return root; } protected class EventoInterno extends Evento { DOMWriter praQuem; public EventoInterno(DOMWriter subEtapa) { super(); praQuem = subEtapa; } public void recebeElemento(InterfaceElemento e) { praQuem.trateElementosExternos(e); } } 112 } package modelo; import java.io.IOException; import controle.Evento; /** * @author Leo * @version 1.1 * @created 28 de Novembro de 2005 */ public interface InterfaceReader { /** * Método responsável por ler o documento XSD fonte e gerar eventos para a * classe passada como parâmetro * * @param fileAbrir * Nome do arquivo fonte XSD que será aberto * @param fileGerado * Nome que se deseja externar após o processamento do arquivo * fonte * @param event * Instância de classe responsável por tratar os elementos * gerados * @throws IOException * @throws Exception */ public abstract void makeData(String fileAbrir, String fileGerado, Evento event) throws IOException, Exception; } package modelo; import java.io.IOException; import ed.InterfaceElemento; /** * @author Leo * @version 1.1 * @created 28 de Novembro de 2005 */ public interface InterfaceWriter { /** * Método que, recebendo uma árvore XML, serializa tal estrutura em um * arquivo * 113 * @param element * Elemento root da estrutura que se quer serializar * @throws IOException */ void output(InterfaceElemento element) throws IOException; } B.8 - SUBETAPAS package subetapas; import interfac.AbstractInterface; import java.util.LinkedList; import java.util.Set; import tratadores.AbstractTratador; import controle.AbstractEtapas; import controle.AbstractObserver; import controle.Persistencia; import ed.InterfaceElemento; import ed.MudancaElemento; /** * @author Leo * @version 1.5 * @created 28 de Novembro de 2005 */ public abstract class AbstractSubEtapa extends AbstractEtapas { protected AbstractInterface interfac; protected LinkedList<AbstractTratador> tratadores; protected Persistencia arqUnico; protected InterfaceElemento root; public AbstractSubEtapa(AbstractInterface i, Set<AbstractObserver> observadores) { super(i, observadores); tratadores = new LinkedList<AbstractTratador>(); interfac = i; root = null; } /** * Adiciona instâncias de classes responsáveis por tratar literalmente os * elementos que trafegam no sistema * * @param tratador * Instância para inserção 114 */ protected final void adicionaTratadores(AbstractTratador tratador) { tratadores.addLast(tratador); } /** * Retira instâncias de classes reponsáveis por tratar literalmente os * elementos que trafegam no sistema * * @param tratador * Instância para retirada */ protected final void removeTratadores(AbstractTratador tratador) { tratadores.remove(tratador); } /* * (non-Javadoc) * * @see controle.AbstractEtapas#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("schema")) this.inicializaSubEtapa(e); try { for (AbstractTratador trat : tratadores) trat.trateElemento(e); } catch (Exception exc) { interfac .recebaInformacoes("O programa executou um erro fatal e será cancelado! " + exc.getLocalizedMessage()); exc.printStackTrace(); System.exit(1); } catch (Throwable thr) { interfac .recebaInformacoes("O programa executou um erro fatal e será cancelado! " + thr.getLocalizedMessage()); thr.printStackTrace(); System.exit(1); } if (e.getName().equals("exit")) this.finalizaSubEtapa(e); 115 } /** * Realiza todas as tarefas necessárias para o funcionamento da subEtapa * antes que ela comece sua execução * * @param e * Elemento em voga no tratamento */ protected void inicializaSubEtapa(InterfaceElemento e) { root = e; } /** * Realiza todas as tarefas necessárias para o funcionamento da subEtapa * depois que ela termina sua execução * * @param e * Elemento em voga no tratamento */ protected void finalizaSubEtapa(InterfaceElemento e) { arqUnico.addContent(root); arqUnico.close(); interfac.recebaInformacoes("A etapa " + this.getClass().getSimpleName() + " foi finalizada. O arquivo gerado por ela encontrase em " + nomeArqSaida); } /** * Método para interação com o usuário especialista. Todas as informações * necessárias para a tomada de decisão estão presentes: a regra que deseja * interagir, qual o assunto da interação e quais elementos são atingidos * * @param regra * Nome da regra que deseja a interação * @param oQue * A causa da interação * @param elemento * Quais elementos são atingidos com tal interação * @return Resposta dependente do usuário especialista */ 116 public LinkedList<String> intervencaoUsuarioEspecialista(String regra, String oQue, String elemento) { return interfac.intervencaoUsuarioEspecialista(regra, oQue, elemento); } public void mandeInformacoesInterface(String mensagem) { interfac.recebaInformacoes(mensagem); } /* * (non-Javadoc) * * @see controle.AbstractMudancas#setMudanca(ed.MudancaElemento) */ public void setMudanca(MudancaElemento m) { mudanca = m; this.notifyEveryOne(); } } package subetapas; import interfac.Interface; import java.util.Set; import tratadores.ConteudoMisto; import tratadores.ConversaoDeAtributos; import tratadores.ConversaoDeElementosComplexos; import tratadores.ConversaoDeElementosEAtributosDoTipoList; import tratadores.ConversaoDeElementosEAtributosDoTipoUnion; import tratadores.ConversaoDeElementosSimples; import tratadores.ConversaoDeTipos; import tratadores.Qualificacao; import controle.AbstractObserver; import controle.Persistencia; /** * @author Leo * @version 1.3 * @created 28 de Novembro de 2005 */ public class Conversao_Fase1 extends AbstractSubEtapa { public Conversao_Fase1(Interface i, Set<AbstractObserver> observadores) { super(i, observadores); nomeArqSaida = "Processo.Conversao.1.xml"; arqUnico = new Persistencia(nomeArqSaida); this.adicionaTratadores(new ConversaoDeElementosComplexos(this)); 117 this.adicionaTratadores(new ConversaoDeElementosSimples(this)); this.adicionaTratadores(new Qualificacao(this)); this.adicionaTratadores(new ConversaoDeTipos(this)); this.adicionaTratadores(new ConversaoDeAtributos(this)); this.adicionaTratadores(new ConteudoMisto(this)); this.adicionaTratadores(new ConversaoDeElementosEAtributosDoTipoList( this)); this.adicionaTratadores(new ConversaoDeElementosEAtributosDoTipoUnion( this)); } } package subetapas; import interfac.Interface; import java.util.Set; import tratadores.ConversaoDeAtributosDoTipoAnyAttbribute; import tratadores.ConversaoDeRelacionamentosDeElementosAny; import tratadores.ConversaoDeRelacionamentosDeElementosComRepeticao; import tratadores.ConversaoDeRelacionamentosDeElementosDefinidosPorReferencia ; import tratadores.ConversaoDeRelacionamentosEmModelosDeConteudoComplexos; import controle.AbstractObserver; import controle.Persistencia; /** * @author Leo * @version 1.3 * @created 28 de Novembro de 2005 */ public class Conversao_Fase2 extends AbstractSubEtapa { public Conversao_Fase2(Interface i, Set<AbstractObserver> observadores) { super(i, observadores); nomeArqSaida = "Processo.Conversao.2.xml"; arqUnico = new Persistencia(nomeArqSaida); // colocado aqui pois se adianta relacionando elementos internos this .adicionaTratadores(new ConversaoDeRelacionamentosEmModelosDeConteudoComplexos( this)); 118 // colocado aqui pois pode acontecer de referenciar elementos futuros // (ver) this .adicionaTratadores(new ConversaoDeRelacionamentosDeElementosDefinidosPorReferencia( this)); // colocado aqui pois se adianta relacionando elementos internos this .adicionaTratadores(new ConversaoDeRelacionamentosDeElementosComRepeticao( this)); this.adicionaTratadores(new ConversaoDeAtributosDoTipoAnyAttbribute( this)); this.adicionaTratadores(new ConversaoDeRelacionamentosDeElementosAny( this)); } } package subetapas; import interfac.Interface; import java.util.Set; import tratadores.ConversaoDeRelacionamentosEntreTiposEElementosComplexos; import tratadores.ConversaoDeRelacionamentosEntreTiposEElementosSimples; import tratadores.Disjuncao; import controle.AbstractObserver; import controle.Persistencia; /** * @author Leo * @version 1.3 * @created 28 de Novembro de 2005 */ public class Conversao_Fase3 extends AbstractSubEtapa { public Conversao_Fase3(Interface i, Set<AbstractObserver> observadores) { super(i, observadores); nomeArqSaida = "Processo.Conversao.3.xml"; arqUnico = new Persistencia(nomeArqSaida); // como a regra copia os relacionamentos jah existentes do tipo para o // elemento as duas regras // abaixo precisaram ser postas aqui this 119 .adicionaTratadores(new ConversaoDeRelacionamentosEntreTiposEElementosComplexos( this)); this .adicionaTratadores(new ConversaoDeRelacionamentosEntreTiposEElementosSimples( this)); // a disjuncao precisa ser criada depois de associado as referencias ao // elemento complexo // pois somente a disjuncao em si eh criada this.adicionaTratadores(new Disjuncao(this)); } } package subetapas; import interfac.Interface; import java.util.Iterator; import java.util.List; import java.util.Set; import org.jdom.Attribute; import tratadores.HerancaDeTiposPorElementos; import tratadores.HerancaDeTiposPorTipos; import controle.AbstractObserver; import controle.Persistencia; import ed.Elemento; import ed.InterfaceElemento; import ed.PreDefinicoes; /** * @author Leo * @version 1.3 * @created 28 de Novembro de 2005 */ public class Conversao_Fase4 extends AbstractSubEtapa { public Conversao_Fase4(Interface i, Set<AbstractObserver> observadores) { super(i, observadores); nomeArqSaida = "Processo.Conversao.4.xml"; arqUnico = new Persistencia(nomeArqSaida); // a heranca precisa ficar a parte jah que todas as relacoes precisam // estar setadas // uma vez que elas copiam integralmente as relacoes de um elemento, por // exemplo this.adicionaTratadores(new HerancaDeTiposPorElementos(this)); this.adicionaTratadores(new HerancaDeTiposPorTipos(this)); } 120 protected void finalizaSubEtapa(InterfaceElemento e) { this.limpeElementos(root); arqUnico.addContent(root); arqUnico.close(); interfac.recebaInformacoes("A etapa " + this.getClass().getSimpleName() + " foi finalizada. O arquivo gerado por ela encontrase em " + nomeArqSaida); } private void limpeElementos(InterfaceElemento root) { List att = root.getAttributes(); int i = 0; while (i < att.size()) { Attribute aux = (Attribute) att.get(i); if (PreDefinicoes.ehTagAdicional(aux.getName())) att.remove(i); else i++; } List f = root.getChildren(); Iterator iterator = f.iterator(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); this.limpeElementos(elemFilho); } } } package subetapas; import interfac.Interface; import java.util.Set; import tratadores.ProcessamentoEInclusaoDeEsquemasExternos; import controle.AbstractObserver; import controle.Persistencia; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public class PreProcessamento_Fase1 extends AbstractSubEtapa { public PreProcessamento_Fase1(Interface i, Set<AbstractObserver> observadores) { super(i, observadores); nomeArqSaida = "Processo.PreProcessamento.1.xml"; arqUnico = new Persistencia(nomeArqSaida); this.adicionaTratadores(new ProcessamentoEInclusaoDeEsquemasExternos( this)); } 121 } package subetapas; import interfac.Interface; import java.util.Set; import tratadores.RemocaoDeElementosETiposSemanticamenteDesnecessarios; import controle.AbstractObserver; import controle.Persistencia; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public class PreProcessamento_Fase2 extends AbstractSubEtapa { public PreProcessamento_Fase2(Interface i, Set<AbstractObserver> observadores) { super(i, observadores); nomeArqSaida = "Processo.PreProcessamento.2.xml"; arqUnico = new Persistencia(nomeArqSaida); this.adicionaTratadores(new RemocaoDeElementosETiposSemanticamenteDesnecessarios( this)); }} package subetapas; import interfac.Interface; import java.util.Set; import tratadores.SubstituicaoDeGruposDeElementosEAtributos; import controle.AbstractObserver; import controle.Persistencia; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public class PreProcessamento_Fase3 extends AbstractSubEtapa { public PreProcessamento_Fase3(Interface i, Set<AbstractObserver> observadores) { super(i, observadores); nomeArqSaida = "Processo.PreProcessamento.3.xml"; arqUnico = new Persistencia(nomeArqSaida); this.adicionaTratadores(new SubstituicaoDeGruposDeElementosEAtributos( this)); } 122 } package subetapas; import interfac.Interface; import java.util.Set; import tratadores.RedefinicaoDeEstruturasAninhadasAnonimas; import controle.AbstractObserver; import controle.Persistencia; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public class PreProcessamento_Fase4 extends AbstractSubEtapa { public PreProcessamento_Fase4(Interface i, Set<AbstractObserver> observadores) { super(i, observadores); nomeArqSaida = "Processo.PreProcessamento.4.xml"; arqUnico = new Persistencia(nomeArqSaida); this.adicionaTratadores(new RedefinicaoDeEstruturasAninhadasAnonimas( this)); } } package subetapas; import interfac.Interface; import java.util.Set; import tratadores.RenomeacaoDeElementosEAtributos; import controle.AbstractObserver; import controle.Persistencia; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public class PreProcessamento_Fase5 extends AbstractSubEtapa { public PreProcessamento_Fase5(Interface i, Set<AbstractObserver> observadores) { super(i, observadores); nomeArqSaida = "Processo.PreProcessamento.5.xml"; arqUnico = new Persistencia(nomeArqSaida); this.adicionaTratadores(new RenomeacaoDeElementosEAtributos(this)); } 123 } package subetapas; import interfac.Interface; import java.util.Set; import tratadores.RemocaoDeTipos; import controle.AbstractObserver; import controle.Persistencia; /** * @author Leo * @version 1.3 * @created 28 de Novembro de 2005 */ public class Reestruturacao extends AbstractSubEtapa { public Reestruturacao(Interface i, Set<AbstractObserver> observadores) { super(i, observadores); nomeArqSaida = "Processo.Reestruturacao.1.xml"; arqUnico = new Persistencia(nomeArqSaida); this.adicionaTratadores(new RemocaoDeTipos(this)); } } B.9 - TRATADORES package tratadores; import subetapas.AbstractSubEtapa; import ed.InterfaceElemento; /** * @author Leo * @version 1.4 * @created 28 de Novembro de 2005 */ public abstract class AbstractTratador { protected int ID; protected AbstractSubEtapa etapaPai; /** * As instâncias que estendem esta classe são responsáveis por tratar o * elementos que trafegam no sistema * * @param e * Elemento para ser processado * @throws Throwable */ 124 public abstract void trateElemento(InterfaceElemento e) throws Throwable; } package tratadores; import java.util.Iterator; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Conceito; import ed.Elemento; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public class ConteudoMisto extends AbstractTratador { public ConteudoMisto(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("element") && e.ehComplexo()) { InterfaceElemento elementpComplexType = this .procureElementoComplexType(e); if (elementpComplexType != null) if (elementpComplexType.getAttributeValue("mixed") != null) if (elementpComplexType.getAttributeValue("mixed").equals( "true")) if (e.getAttributeValue("name") != null) { etapaPai.setMudanca(new Conceito("CMis", e .getAttributeValue("name") + "Texto", true)); etapaPai.setMudanca(new Relacao("CMis", e .getAttributeValue("name"), e .getAttributeValue("name") + "Texto", 0, -1, 1, 1)); } } 125 } private InterfaceElemento procureElementoComplexType(InterfaceElemento el) { List f = el.getChildren(); Iterator iterator = f.iterator(); InterfaceElemento resposta = null; while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (!elemFilho.getName().equals("element")) { InterfaceElemento aux = this .procureElementoComplexType(elemFilho); if (aux != null) resposta = aux; } } if (el.getName().equals("complexType")) resposta = el; return resposta; }} package tratadores; import java.util.LinkedList; import subetapas.AbstractSubEtapa; import ed.Conceito; import ed.InterfaceElemento; import ed.PreDefinicoes; import ed.Relacao; /** * @author Leo * @version 1.7 * @created 28 de Novembro de 2005 */ public class ConversaoDeAtributos extends AbstractTratador { public ConversaoDeAtributos(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { // ver enumeraçao de valores if (e.getName().equals("attribute")) if (e.getParentElement().ehComplexo()) this.construaMudancaElemento(e); } private void construaMudancaElemento(InterfaceElemento e) { // nada eh gerado caso a clausula seja prohibited if (e.getAttributeValue("use") != null) if (e.getAttributeValue("use").equals("prohibited")) return; 126 if (e.getAttributeValue("type") != null && !e.getAttributeValue("type").equals("anyAttribute")) { if (e.getAttributeValue("type").equals("list") || e.getAttributeValue("type").equals("union")) { if (e.getAttributeValue("name") != null) etapaPai.setMudanca(new Conceito("AT", e .getAttributeValue("name"), false)); } else if (PreDefinicoes.ehTipoPreDefinido(e .getAttributeValue("type"))) if (e.getAttributeValue("name") != null) { etapaPai.setMudanca(new Conceito("AT", e .getAttributeValue("name"), true, e .getInformacoesPreDefinidas())); } else if (e.getAttributeValue("name") != null) etapaPai.setMudanca(new Conceito("AT", e .getAttributeValue("name"), true, e .getInformacoesPreDefinidas())); // relação if (e.getAttributeValue("name") != null && this.verdadeiroPai(e) != null) { LinkedList<String> cardInversa = etapaPai .intervencaoUsuarioEspecialista("AT", "CardR", e .caminhoDOM() + " => " + this.verdadeiroPai(e)); if (cardInversa.get(0).equals("default")) { cardInversa = new LinkedList<String>(); cardInversa.add(0, "1"); cardInversa.add(1, "-1"); } if (e.getAttributeValue("use") != null) { if (e.getAttributeValue("use").equals("optional")) etapaPai.setMudanca(new Relacao("AT", this .verdadeiroPai(e), e.getAttributeValue("name"), 0, 1, Integer.parseInt(cardInversa.get(0)), Integer.parseInt(cardInversa.get(1)))); else if (e.getAttributeValue("use").equals("required")) etapaPai.setMudanca(new Relacao("AT", this .verdadeiroPai(e), e.getAttributeValue("name"), 1, 1, Integer.parseInt(cardInversa.get(0)), 127 Integer.parseInt(cardInversa.get(1)))); } else etapaPai.setMudanca(new Relacao("AT", this.verdadeiroPai(e), e.getAttributeValue("name"), 1, -1, Integer.parseInt(cardInversa.get(0)), Integer.parseInt(cardInversa.get(1)))); } } } private String verdadeiroPai(InterfaceElemento el) { el = el.getParentElement(); while ((!el.getName().equals("element") && !el.getName().equals("complexType") || el .getAttributeValue("name") == null) && !el.getName().equals("schema")) el = el.getParentElement(); if (el.getAttributeValue("name") != null) return el.getAttributeValue("name"); else return null; } } package tratadores; import java.util.LinkedList; import subetapas.AbstractSubEtapa; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.5 * @created 28 de Novembro de 2005 */ public class ConversaoDeAtributosDoTipoAnyAttbribute extends AbstractTratador { public ConversaoDeAtributosDoTipoAnyAttbribute(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * 128 * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("attribute")) if (e.getAttributeValue("type") != null) if (e.getAttributeValue("type").equals("anyAttribute")) { if (this.verdadeiroPai(e).ehComplexo()) { if (this.verdadeiroPai(e).getAttributeValue("name") != null) { LinkedList<String> cardInversa = etapaPai .intervencaoUsuarioEspecialista("ATAny", "Relação", e.caminhoDOM() + " => " + e.getParentElement() .caminhoDOM()); if (cardInversa.get(0).equals("default")) etapaPai.setMudanca(new Relacao("ATAny", this .verdadeiroPai(e).getAttributeValue( "name"), "any", 0, 1, 0, -1)); else etapaPai.setMudanca(new Relacao("ATAny", this .verdadeiroPai(e).getAttributeValue( "name"), "any", 0, 1, Integer .parseInt(cardInversa.get(0)), Integer .parseInt(cardInversa.get(1)))); } } } } private InterfaceElemento verdadeiroPai(InterfaceElemento el) { el = el.getParentElement(); while ((!el.getName().equals("element") && !el.getName().equals("complexType") || el .getAttributeValue("name") == null) 129 && !el.getName().equals("schema")) el = el.getParentElement(); if (el.getAttributeValue("name") != null) return el; else return null; } } package tratadores; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Conceito; import ed.Elemento; import ed.InterfaceElemento; /** * @author Leo * @version 1.5 * @created 28 de Novembro de 2005 */ public class ConversaoDeElementosComplexos extends AbstractTratador { public ConversaoDeElementosComplexos(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { // ver elementos vazios.. possibilidade de colocar tags nos elementos! if (e.getName().equals("element")) if (e.ehComplexo()) { if (e.ehVazio()) { if (e.getTag("qualificacao") == null) { LinkedList<String> respostaElementoVazio = etapaPai .intervencaoUsuarioEspecialista("EC", "Qualificação", e.caminhoDOM()); 130 if (respostaElementoVazio.get(0).equals("sim")) { // coloca todos os filhos como qualificacao this.setaRegraQ(e, true); return; } else { this.setaRegraQ(e, false); } } } if ((e.getTag("qualificacao") == null) || (!e.getTag("qualificacao").equals("true"))) if (e.getAttributeValue("name") != null) etapaPai.setMudanca(new Conceito("EC", e .getAttributeValue("name"), false)); } } private void setaRegraQ(InterfaceElemento el, boolean escolha) { Elemento etapaPai = el.getParentElement(); List f = etapaPai.getChildren(); Iterator iterator = f.iterator(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (elemFilho.getName().equals(el.getName())) elemFilho.setTag("qualificacao", "" + escolha); } } } package tratadores; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Conceito; import ed.Elemento; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.4 * @created 28 de Novembro de 2005 */ public class ConversaoDeElementosEAtributosDoTipoList extends AbstractTratador { 131 public ConversaoDeElementosEAtributosDoTipoList(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("attribute") || (e.getName().equals("element") && !e.ehComplexo())) { LinkedList<InterfaceElemento> elemList = this.procurePorList(e); if (elemList.size() > 0) if (e.getAttributeValue("name") != null) { LinkedList<String> anotacoes = new LinkedList<String>(); anotacoes.addLast("tipo=xs:string"); etapaPai.setMudanca(new Conceito("RList", e .getAttributeValue("name") + "Lista", true, anotacoes)); LinkedList<String> cardI = etapaPai .intervencaoUsuarioEspecialista("RList", "CardR", e .caminhoDOM()); etapaPai.setMudanca(new Relacao("RList", e .getAttributeValue("name"), e .getAttributeValue("name") + "Lista", 1, -1, Integer.parseInt(cardI.get(0)), Integer.parseInt(cardI.get(1)))); } } } private LinkedList<InterfaceElemento> procurePorList(InterfaceElemento el) { List f = el.getChildren(); Iterator iterator = f.iterator(); LinkedList<InterfaceElemento> resposta = new LinkedList<InterfaceElemento>(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (!elemFilho.getName().equals("element")) resposta.addAll(this.procurePorList(elemFilho)); 132 } if (el.getName().equals("list")) resposta.addLast(el); return resposta; } } package tratadores; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Conceito; import ed.Elemento; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.4 * @created 28 de Novembro de 2005 */ public class ConversaoDeElementosEAtributosDoTipoUnion extends AbstractTratador { public ConversaoDeElementosEAtributosDoTipoUnion(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("attribute") || (e.getName().equals("element") && !e.ehComplexo())) { LinkedList<InterfaceElemento> elemList = this.procurePorUnion(e); if (elemList.size() > 0) if (e.getAttributeValue("name") != null) { Iterator it = elemList.iterator(); while (it.hasNext()) { InterfaceElemento elemL = (InterfaceElemento) it.next(); 133 if (elemL.getAttributeValue("memberTypes") != null) { String memberTypes = elemL.getAttributeValue( "memberTypes").trim(); String[] nomesSeparados = memberTypes.split("\\s"); for (int i = 0; i < nomesSeparados.length; i++) { etapaPai.setMudanca(new Conceito("RUnion", e .getAttributeValue("name") + "Uniao" + (i + 1), true)); LinkedList<Integer> cardD = elemL .apliqueCardD(); LinkedList<String> cardI = etapaPai .intervencaoUsuarioEspecialista( "RUnion", "CardR", elemL .caminhoDOM()); etapaPai.setMudanca(new Relacao("RUnion", e .getAttributeValue("name"), e .getAttributeValue("name") + "Uniao" + (i + 1), cardD.getFirst() .intValue(), cardD.getLast().intValue(), Integer .parseInt(cardI.get(0)), Integer.parseInt(cardI.get(1)))); } } } } } } private LinkedList<InterfaceElemento> procurePorUnion(InterfaceElemento el) { List f = el.getChildren(); Iterator iterator = f.iterator(); LinkedList<InterfaceElemento> resposta = new LinkedList<InterfaceElemento>(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); 134 if (!elemFilho.getName().equals("element")) resposta.addAll(this.procurePorUnion(elemFilho)); } if (el.getName().equals("union")) resposta.addLast(el); return resposta; } } package tratadores; import subetapas.AbstractSubEtapa; import ed.Conceito; import ed.InterfaceElemento; import ed.PreDefinicoes; /** * @author Leo * @version 1.5 * @created 28 de Novembro de 2005 */ public class ConversaoDeElementosSimples extends AbstractTratador { public ConversaoDeElementosSimples(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("element")) if (!e.ehComplexo()) if (PreDefinicoes.ehTipoPreDefinido(e.getTipoElementoSimples())) { if (e.getTipoElementoSimples().equals("list") || e.getTipoElementoSimples().equals("union")) { if (e.getAttributeValue("name") != null) etapaPai.setMudanca(new Conceito("ES", e .getAttributeValue("name"), false)); } else { // tipos pre-definidos nao sendo list e union if (e.getAttributeValue("name") != null) 135 etapaPai.setMudanca(new Conceito("ES", e .getAttributeValue("name"), true, e .getInformacoesPreDefinidas())); } } else if (e.getAttributeValue("name") != null) etapaPai.setMudanca(new Conceito("ES", e .getAttributeValue("name"), false)); } } package tratadores; import java.util.LinkedList; import subetapas.AbstractSubEtapa; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.4 * @created 28 de Novembro de 2005 */ public class ConversaoDeRelacionamentosDeElementosAny extends AbstractTratador { public ConversaoDeRelacionamentosDeElementosAny(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if ((e.getName().equals("element") && (e.getAttributeValue("type") != null) && (e .getAttributeValue("type").matches(".*anyType"))) || (e.getName().equals(("any")))) { LinkedList<Integer> cardD = e.apliqueCardD(); LinkedList<String> cardI = etapaPai.intervencaoUsuarioEspecialista( "RAny", "CardR", e.caminhoDOM()); if (e.getAttributeValue("name") != null) etapaPai .setMudanca(new Relacao("RAny", e 136 .getAttributeValue("name"), "RAny", cardD .get(0).intValue(), cardD.get(1).intValue(), Integer.parseInt(cardI.get(0)), Integer .parseInt(cardI.get(1)))); } } } package tratadores; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Elemento; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.5 * @created 28 de Novembro de 2005 */ public class ConversaoDeRelacionamentosDeElementosComRepeticao extends AbstractTratador { public ConversaoDeRelacionamentosDeElementosComRepeticao( AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @SuppressWarnings("unchecked") @Override public void trateElemento(InterfaceElemento e) { // ver como definir subgrupos if ((e.getName().equals("element") && e.ehComplexo())) { List elemetosParaAplicacaoDeRegra = this .temDeclaracaoRepetidaDeElementosInternos(e); if (elemetosParaAplicacaoDeRegra.size() > 0) { this.apliqueRegraRER(e, elemetosParaAplicacaoDeRegra); } } 137 } private void apliqueRegraRER(InterfaceElemento elemPai, List<Elemento> elemRegraRMC) { LinkedList<String> nomeGruposJahAplicadaRegra = new LinkedList<String>(); if (elemPai.getAttributeValue("name") != null) { Iterator it = elemRegraRMC.iterator(); while (it.hasNext()) { Elemento elems = (Elemento) it.next(); LinkedList<String> classificacaoGrupo = etapaPai .intervencaoUsuarioEspecialista("RER", "Classificação", elems.caminhoDOM()); elems.setTag("grupo", classificacaoGrupo.get(0)); } it = elemRegraRMC.iterator(); while (it.hasNext()) { Elemento elems = (Elemento) it.next(); if (!nomeGruposJahAplicadaRegra.contains(elems.getTag("grupo"))) { nomeGruposJahAplicadaRegra.addLast(elems.getTag("grupo")); LinkedList<Integer> cardD = elems.apliqueCardR(elems .getTag("grupo")); LinkedList<String> resposta = etapaPai .intervencaoUsuarioEspecialista("RER", "CardR", elems.caminhoDOM()); etapaPai.setMudanca(new Relacao("RER", elemPai .getAttributeValue("name"), elems .getAttributeValue("name"), cardD.get(0), cardD .get(1), Integer.parseInt(resposta.get(0)), Integer .parseInt(resposta.get(1)))); } } } } private List<Elemento> temDeclaracaoRepetidaDeElementosInternos( InterfaceElemento elem) { List<Elemento> elemDiferentesDeclarados = new LinkedList<Elemento>(); List f = elem.getChildren(); Iterator iterator = f.iterator(); 138 while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (elemFilho.getName().equals("all") || elemFilho.getName().equals("choice") || elemFilho.getName().equals("sequence") || elemFilho.getName().equals("restriction") || elemFilho.getName().equals("extension") || elemFilho.getName().equals("complexType")) elemDiferentesDeclarados.addAll(this .temDeclaracaoRepetidaDeElementosInternos(elemFilho)); else if (elemFilho.getName().equals("element")) { if (elemFilho.ehVazio()) { if (elemFilho.getTag("qualificacao") == null) { LinkedList<String> resposta = etapaPai .intervencaoUsuarioEspecialista("RER", "Qualificação", elemFilho.caminhoDOM()); if (resposta.removeFirst().equals("sim")) this.setaRegraQ(elemFilho, true); else this.setaRegraQ(elemFilho, false); } } if ((elemFilho.getTag("qualificacao") == null) || (elemFilho.getTag("qualificacao").equals("false"))) if (elemFilho.possuiElementosIrmaosIguais()) elemDiferentesDeclarados.add(elemFilho); } } return elemDiferentesDeclarados; } private void setaRegraQ(InterfaceElemento el, boolean escolha) { Elemento etapaPai = el.getParentElement(); List f = etapaPai.getChildren(); Iterator iterator = f.iterator(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (elemFilho.getName().equals(el.getName())) elemFilho.setTag("qualificacao", "" + escolha); } } } 139 package tratadores; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Elemento; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.5 * @created 28 de Novembro de 2005 */ public class ConversaoDeRelacionamentosDeElementosDefinidosPorReferencia extends AbstractTratador { InterfaceElemento root; public ConversaoDeRelacionamentosDeElementosDefinidosPorReferencia( AbstractSubEtapa subEtapa) { etapaPai = subEtapa; root = new Elemento(); } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("schema")) root = e; else if (e.getName().equals("element")) if (e.getAttributeValue("ref") != null) if (this.temDeclaracaoDeElemento(root, e .getAttributeValue("ref"))) { LinkedList<Integer> cardD = e.apliqueCardD(); LinkedList<String> cardI = etapaPai .intervencaoUsuarioEspecialista("RREF", "CardR", e .caminhoDOM()); etapaPai.setMudanca(new Relacao("RREF", this .verdadeiroPai(e), e.getAttributeValue("ref"), 140 cardD.get(0).intValue(), cardD.get(1).intValue(), Integer.parseInt(cardI.get(0)), Integer .parseInt(cardI.get(1)))); } } private String verdadeiroPai(InterfaceElemento el) { el = el.getParentElement(); while ((!el.getName().equals("element") && !el.getName().equals("complexType") || el .getAttributeValue("name") == null) && !el.getName().equals("schema")) el = el.getParentElement(); if (el.getAttributeValue("name") != null) return el.getAttributeValue("name"); else return null; } private boolean temDeclaracaoDeElemento(InterfaceElemento root, String attributeValue) { List f = root.getChildren(); Iterator iterator = f.iterator(); boolean resposta = false; while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); resposta = resposta || this.temDeclaracaoDeElemento(elemFilho, attributeValue); } if (root.getName().equals("element")) if (root.getAttributeValue("name") != null) if (root.getAttributeValue("name").equals(attributeValue)) return true; return resposta; }} package tratadores; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Elemento; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo 141 * @version 1.4 * @created 28 de Novembro de 2005 */ public class ConversaoDeRelacionamentosEmModelosDeConteudoComplexos extends AbstractTratador { public ConversaoDeRelacionamentosEmModelosDeConteudoComplexos( AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @SuppressWarnings("unchecked") @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("complexType") || ((e.getName().equals("element") && e.ehComplexo()))) { List elemetosParaAplicacaoDeRegra = this .temDeclaracaoNaoRepetidaDeElementosInternos(e); if (elemetosParaAplicacaoDeRegra.size() > 0) { this.apliqueRegraRMC(e, elemetosParaAplicacaoDeRegra); } } } private void apliqueRegraRMC(InterfaceElemento elemPai, List<Elemento> elemRegraRMC) { if (elemPai.getAttributeValue("name") != null) { Iterator it = elemRegraRMC.iterator(); while (it.hasNext()) { Elemento elemRMC = (Elemento) it.next(); if (elemRMC.getAttributeValue("name") != null) { LinkedList<Integer> cardD = elemRMC.apliqueCardD(); if (!(cardD.get(0).intValue() == 0 && cardD.get(1) .intValue() == 0)) { LinkedList<String> resposta = etapaPai .intervencaoUsuarioEspecialista("RMC", "CardR", elemRMC.caminhoDOM()); etapaPai.setMudanca(new Relacao("RMC", elemPai .getAttributeValue("name"), elemRMC 142 .getAttributeValue("name"), cardD.get(0) .intValue(), cardD.get(1).intValue(), Integer .parseInt(resposta.get(0)), Integer .parseInt(resposta.get(1)))); } } } } } private List<Elemento> temDeclaracaoNaoRepetidaDeElementosInternos( InterfaceElemento elem) { List<Elemento> elemDiferentesDeclarados = new LinkedList<Elemento>(); List f = elem.getChildren(); Iterator iterator = f.iterator(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (elemFilho.getName().equals("all") || elemFilho.getName().equals("choice") || elemFilho.getName().equals("sequence") || elemFilho.getName().equals("restriction") || elemFilho.getName().equals("extension") || elemFilho.getName().equals("complexType")) elemDiferentesDeclarados .addAll(this .temDeclaracaoNaoRepetidaDeElementosInternos(elemFilho)); else if (elemFilho.getName().equals("element")) { if (elemFilho.ehVazio()) { if (elemFilho.getTag("qualificacao") != null) { LinkedList<String> resposta = etapaPai .intervencaoUsuarioEspecialista("RMC", "Qualificação", elemFilho.caminhoDOM()); if (resposta.removeFirst().equals("sim")) elemFilho.setTag("qualificacao", "true"); else elemFilho.setTag("qualificacao", "false"); } } if ((elemFilho.getTag("qualificacao") == null) || (elemFilho.getTag("qualificacao").equals("false"))) if (!elemFilho.possuiElementosIrmaosIguais()) elemDiferentesDeclarados.add(elemFilho); } } return elemDiferentesDeclarados; 143 }} package tratadores; import java.util.Iterator; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Elemento; import ed.InterfaceElemento; import ed.PreDefinicoes; import ed.Relacao; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public class ConversaoDeRelacionamentosEntreTiposEElementosComplexos extends AbstractTratador { InterfaceElemento root; public ConversaoDeRelacionamentosEntreTiposEElementosComplexos( AbstractSubEtapa subEtapa) { etapaPai = subEtapa; root = new Elemento(); } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { // RTEC if (e.getName().equals("schema")) root = e; else if (e.getName().equals("element")) if (e.getAttributeValue("type") != null && !PreDefinicoes.ehTipoPreDefinido(e .getAttributeValue("type"))) if (this.temDeclaracaoDeTipo(root, e.getAttributeValue("type"))) if (e.getAttributeValue("name") != null) etapaPai.setMudanca(new Relacao("RTEC", e .getAttributeValue("name"), e .getAttributeValue("type"), 0, 0, 0, 0)); } 144 private boolean temDeclaracaoDeTipo(InterfaceElemento root, String attributeValue) { List f = root.getChildren(); Iterator iterator = f.iterator(); boolean resposta = false; while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); resposta = resposta || this.temDeclaracaoDeTipo(elemFilho, attributeValue); } if (root.getName().equals("complexType")) if (root.getAttributeValue("name") != null) if (root.getAttributeValue("name").equals(attributeValue)) return true; return resposta; } } package tratadores; import java.util.Iterator; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Elemento; import ed.InterfaceElemento; import ed.PreDefinicoes; import ed.Relacao; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public class ConversaoDeRelacionamentosEntreTiposEElementosSimples extends AbstractTratador { InterfaceElemento root; public ConversaoDeRelacionamentosEntreTiposEElementosSimples( AbstractSubEtapa subEtapa) { etapaPai = subEtapa; root = new Elemento(); } /* * (non-Javadoc) 145 * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { // RTES -> ver necessidade de copiar informacoes de restricao gerada na // regra Rlist e RUnion if (e.getName().equals("schema")) root = e; else if (e.getName().equals("element")) if (e.getAttributeValue("type") != null && !PreDefinicoes.ehTipoPreDefinido(e .getAttributeValue("type"))) if (this.temDeclaracaoDeTipo(root, e.getAttributeValue("type"))) if (e.getAttributeValue("name") != null) etapaPai.setMudanca(new Relacao("RTES", e .getAttributeValue("name"), e .getAttributeValue("type"), 0, 0, 0, 0)); } private boolean temDeclaracaoDeTipo(InterfaceElemento root, String attributeValue) { List f = root.getChildren(); Iterator iterator = f.iterator(); boolean resposta = false; while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); resposta = resposta || this.temDeclaracaoDeTipo(elemFilho, attributeValue); } if (root.getName().equals("simpleType")) if (root.getAttributeValue("name") != null) if (root.getAttributeValue("name").equals(attributeValue)) return true; return resposta; } } package tratadores; import subetapas.AbstractSubEtapa; import ed.Conceito; 146 import ed.InterfaceElemento; import ed.PreDefinicoes; /** * @author Leo * @version 1.5 * @created 28 de Novembro de 2005 */ public class ConversaoDeTipos extends AbstractTratador { public ConversaoDeTipos(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("complexType") || e.getName().equals("simpleType")) this.apliqueRegra(e); } private void apliqueRegra(InterfaceElemento e) { if (e.getName().equals("complexType")) { if (e.getAttributeValue("name") != null) etapaPai.setMudanca(new Conceito("T", e .getAttributeValue("name"), false)); } else if (e.getName().equals("simpleType")) { if (PreDefinicoes.ehTipoPreDefinido(e.getTipoElementoSimples())) { if (e.getAttributeValue("name") != null) etapaPai.setMudanca(new Conceito("T", e .getAttributeValue("name"), false, e .getInformacoesPreDefinidas())); } else if (e.getAttributeValue("name") != null) etapaPai.setMudanca(new Conceito("T", e .getAttributeValue("name"), false)); } } } package tratadores; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import subetapas.AbstractSubEtapa; 147 import ed.Elemento; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.3 * @created 28 de Novembro de 2005 */ public class Disjuncao extends AbstractTratador { InterfaceElemento root; public Disjuncao(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; root = new Elemento(); } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("schema")) root = e; else if (e.getName().equals("choice")) { List f = e.getChildren(); Iterator iterator = f.iterator(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (elemFilho.ehVazio()) { if (elemFilho.getTag("qualificacao") == null) { LinkedList<String> resposta = etapaPai .intervencaoUsuarioEspecialista("Disj", "Qualificacao", elemFilho.caminhoDOM()); if (resposta.removeFirst().equals("sim")) this.apliqueQParaIrmaos(elemFilho, true); else this.apliqueQParaIrmaos(elemFilho, false); } } if (elemFilho.getTag("qualificacao") == null || elemFilho.getTag("qualificacao").equals("false")) if (elemFilho.getAttributeValue("name") != null) etapaPai.setMudanca(new Relacao("Disj", this .verdadeiroPai(e), elemFilho 148 .getAttributeValue("name"), 0, 0, 0, 0)); } } } private String verdadeiroPai(InterfaceElemento el) { el = el.getParentElement(); while ((!el.getName().equals("element") && !el.getName().equals("complexType") || el .getAttributeValue("name") == null) && !el.getName().equals("schema")) el = el.getParentElement(); if (el.getAttributeValue("name") != null) return el.getAttributeValue("name"); else return null; } private void apliqueQParaIrmaos(InterfaceElemento el, boolean escolha) { Elemento etapaPai = el.getParentElement(); List f = etapaPai.getChildren(); Iterator iterator = f.iterator(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (elemFilho.getName().equals(el.getName())) elemFilho.setTag("qualificacao", "" + escolha); } } } package tratadores; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Elemento; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public class HerancaDeTiposPorElementos extends AbstractTratador { 149 InterfaceElemento root; public HerancaDeTiposPorElementos(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; root = new Elemento(); } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("schema")) root = e; else if (e.getName().equals("element")) { LinkedList<InterfaceElemento> elemExtensao = this .busquePorExtensao(e); if (elemExtensao.size() > 0) { Iterator it = elemExtensao.iterator(); while (it.hasNext()) { Elemento extensoes = (Elemento) it.next(); if (extensoes.getAttributeValue("name") != null && e.getAttributeValue("name") != null) etapaPai.setMudanca(new Relacao("HerTE", e .getAttributeValue("name"), extensoes .getAttributeValue("name"), 0, 0, 0, 0)); } } } } private LinkedList<InterfaceElemento> busquePorExtensao(InterfaceElemento el) { List f = el.getChildren(); Iterator iterator = f.iterator(); LinkedList<InterfaceElemento> resposta = new LinkedList<InterfaceElemento>(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (!elemFilho.getName().equals("element")) resposta.addAll(this.busquePorExtensao(elemFilho)); } if (el.getName().equals("extension")) if (el.getAttributeValue("base") != null) resposta.addLast(this.temDeclaracaoDeTipo(root, el .getAttributeValue("base"))); 150 return resposta; } private InterfaceElemento temDeclaracaoDeTipo(InterfaceElemento root, String attributeValue) { List f = root.getChildren(); Iterator iterator = f.iterator(); Elemento resposta = null; while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); InterfaceElemento aux = this.temDeclaracaoDeTipo(elemFilho, attributeValue); if (aux != null) resposta = (Elemento) aux; } if (root.getName().equals("simpleType") || root.getName().equals("complexType")) if (root.getAttributeValue("name") != null) if (root.getAttributeValue("name").equals(attributeValue)) return root; return resposta; }} package tratadores; import java.util.Iterator; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Elemento; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public class HerancaDeTiposPorTipos extends AbstractTratador { InterfaceElemento root; public HerancaDeTiposPorTipos(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; root = new Elemento(); } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) 151 */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("schema")) root = e; else if (e.getName().equals("extension")) if (e.getAttributeValue("base") != null) { InterfaceElemento elemPaiDaBase = this.temDeclaracaoDeTipo( root, e.getAttributeValue("base")); if (elemPaiDaBase != null) etapaPai.setMudanca(new Relacao("HerTT", this .verdadeiroPai(e), elemPaiDaBase .getAttributeValue("name"), 0, 0, 0, 0)); } } private String verdadeiroPai(InterfaceElemento el) { el = el.getParentElement(); while ((!el.getName().equals("element") && !el.getName().equals("complexType") || el .getAttributeValue("name") == null) && !el.getName().equals("schema")) el = el.getParentElement(); if (el.getAttributeValue("name") != null) return el.getAttributeValue("name"); else return null; } private InterfaceElemento temDeclaracaoDeTipo(InterfaceElemento root, String attributeValue) { List f = root.getChildren(); Iterator iterator = f.iterator(); Elemento resposta = null; while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); InterfaceElemento aux = this.temDeclaracaoDeTipo(elemFilho, attributeValue); if (aux != null) resposta = (Elemento) aux; } if (root.getName().equals("simpleType") || root.getName().equals("complexType")) if (root.getAttributeValue("name") != null) if (root.getAttributeValue("name").equals(attributeValue)) return root; 152 return resposta; } } package tratadores; import java.util.Iterator; import java.util.LinkedList; import subetapas.AbstractSubEtapa; import controle.Evento; import ed.Elemento; import ed.InterfaceElemento; /** * @author Leo * @version 1.6 * @created 28 de Novembro de 2005 */ public class ProcessamentoEInclusaoDeEsquemasExternos extends AbstractTratador { EventoInterno eventoI; LinkedList<InterfaceElemento> inclusoes; private InterfaceElemento root; public ProcessamentoEInclusaoDeEsquemasExternos(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; eventoI = new EventoInterno(this); inclusoes = new LinkedList<InterfaceElemento>(); root = null; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ public void trateElemento(InterfaceElemento elem) throws Throwable { if (elem.getName().equals("schema")) root = elem; if (elem.getName().equals("include")) { String nomeArq = elem.getAttributeValue("name"); eventoI.abrirArquivo(nomeArq, ""); } else if (elem.getName().equals("exit")) this.incluaElementos(); } private void incluaElementos() { Iterator iterat = inclusoes.iterator(); while (iterat.hasNext()) { InterfaceElemento incluir = (Elemento) iterat.next(); incluir = incluir.clone(); root.addContent((Elemento) incluir); } 153 while (root.removeChildren("include")) ; } protected void trateElementosExternos(InterfaceElemento elem) { if (elem.getName().equals("schema")) { java.util.List children = elem.getChildren(); Iterator iterator = children.iterator(); while (iterator.hasNext()) { Elemento incluir = (Elemento) iterator.next(); inclusoes.addLast(incluir); } } } protected class EventoInterno extends Evento { protected ProcessamentoEInclusaoDeEsquemasExternos subEtapa; public EventoInterno(ProcessamentoEInclusaoDeEsquemasExternos subEtapa) { super(); this.subEtapa = subEtapa; } public void recebeElemento(InterfaceElemento e) { subEtapa.trateElementosExternos(e); } }} package tratadores; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Conceito; import ed.Elemento; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.4 * @created 28 de Novembro de 2005 */ public class Qualificacao extends AbstractTratador { public Qualificacao(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("element") && e.ehComplexo()) { 154 this.apliqueRegraQ(e); } } private void apliqueRegraQ(InterfaceElemento el) { // ver como fazaer subgrupo List f = el.getChildren(); Iterator iterat = f.iterator(); while (iterat.hasNext()) { Elemento filho = (Elemento) iterat.next(); this.apliqueRegraQ(filho); } if (el.getName().equals("element") && el.getTag("qualificacao") == null) this.crieConceito((Elemento) el); } private void crieConceito(InterfaceElemento filho) { if (filho.getTag("qualificacao") == null) { LinkedList<String> resposta = etapaPai .intervencaoUsuarioEspecialista("Q", "Qualificação", filho .caminhoDOM()); if (resposta.removeFirst().equals("sim")) this.apliqueQParaIrmaos(filho, true); else this.apliqueQParaIrmaos(filho, false); } if (filho.getTag("qualificacao").equals("true")) { LinkedList<String> nomeIrmaos = this.getNomeIrmaos(filho); LinkedList<String> anotacoes = new LinkedList<String>(); anotacoes.addLast("tipo=xs:string"); anotacoes.addLast("enumeracao=" + nomeIrmaos); etapaPai.setMudanca(new Conceito("Q", this.verdadeiroPai(filho) + "Tipo", true, anotacoes)); LinkedList<String> cardI = etapaPai.intervencaoUsuarioEspecialista( "Q", "CardR", filho.caminhoDOM()); if (cardI.getFirst().equals("default")) { cardI = new LinkedList<String>(); cardI.addLast("0"); cardI.addLast("-1"); } etapaPai.setMudanca(new Relacao("Q", this.verdadeiroPai(filho), this.verdadeiroPai(filho) + "Tipo", 1, 1, Integer .parseInt(cardI.get(0)), Integer.parseInt(cardI .get(1)))); } } private LinkedList<String> getNomeIrmaos(InterfaceElemento el) { Elemento etapaPai = el.getParentElement(); 155 List f = etapaPai.getChildren(); Iterator iterator = f.iterator(); LinkedList<String> nomeBrothers = new LinkedList<String>(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (elemFilho.getName().equals(el.getName())) if (elemFilho.getAttributeValue("name") != null) nomeBrothers.addLast(elemFilho.getAttributeValue("name")); } return nomeBrothers; } private void apliqueQParaIrmaos(InterfaceElemento el, boolean escolha) { Elemento etapaPai = el.getParentElement(); List f = etapaPai.getChildren(); Iterator iterator = f.iterator(); while (iterator.hasNext()) { Elemento elemFilho = (Elemento) iterator.next(); if (elemFilho.getName().equals(el.getName())) elemFilho.setTag("qualificacao", "" + escolha); } } private String verdadeiroPai(InterfaceElemento el) { el = el.getParentElement(); while ((!el.getName().equals("element") && !el.getName().equals("complexType") || el .getAttributeValue("name") == null) && !el.getName().equals("schema")) el = el.getParentElement(); if (el.getAttributeValue("name") != null) return el.getAttributeValue("name"); else return null; }} package tratadores; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Elemento; import ed.InterfaceElemento; /** * @author Leo * @version 1.7 * @created 28 de Novembro de 2005 */ 156 public class RedefinicaoDeEstruturasAninhadasAnonimas extends AbstractTratador { private InterfaceElemento root; public RedefinicaoDeEstruturasAninhadasAnonimas(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; root = null; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("schema")) root = e; if (e.getName().equals("choice") || e.getName().equals("sequence")) { if (this.possuiSomenteDeclaracoesAninhadasAnonimas(e)) this.apliqueRegra(e); } } public boolean possuiSomenteDeclaracoesAninhadasAnonimas( InterfaceElemento el) { List f = el.getChildren(); Iterator iterat = f.iterator(); while (iterat.hasNext()) { Elemento filho = (Elemento) iterat.next(); if (filho.getName().equals("sequence") || filho.getName().equals("choice")) { if (filho.getAttributes().size() != 0) return false; } else return false; } return true; } private void apliqueRegra(InterfaceElemento e) { List filhos = new LinkedList(); filhos = e.getChildren(); Iterator iterat = filhos.iterator(); int i = 1; while (iterat.hasNext()) { InterfaceElemento filho = (Elemento) iterat.next(); Elemento casca1 = new Elemento("element", root.getNamespace("xs")); String nomeElemVirtual = ""; if (e.getParentElement().getAttributeValue("name") != null) nomeElemVirtual += e.getParentElement().getAttributeValue( 157 "name"); if (e.getName().equals("choice")) nomeElemVirtual += "Op"; else nomeElemVirtual += "Seq"; nomeElemVirtual += "" + i; casca1.addAttribute("name", nomeElemVirtual); i++; InterfaceElemento casca2 = new Elemento("complexType"); casca1.addContent((Elemento) casca2); casca2.addContent(filho.clone()); e.addContent(casca1); e.removeChildren(filho); } }} package tratadores; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import subetapas.AbstractSubEtapa; import ed.Elemento; import ed.InterfaceElemento; import ed.PreDefinicoes; /** * @author Leo * @version 1.8 * @created 28 de Novembro de 2005 */ public class RemocaoDeElementosETiposSemanticamenteDesnecessarios extends AbstractTratador { LinkedList<String> listaRemocao; LinkedList<InterfaceElemento> tiposNaoReferenciados; InterfaceElemento root; public RemocaoDeElementosETiposSemanticamenteDesnecessarios( AbstractSubEtapa subEtapa) { root = null; etapaPai = subEtapa; listaRemocao = etapaPai.intervencaoUsuarioEspecialista("RET", "Remocao Elementos", ""); tiposNaoReferenciados = new LinkedList<InterfaceElemento>(); } /* * (non-Javadoc) * 158 * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ public void trateElemento(InterfaceElemento e) { if (e.getName().equals("schema")) { root = e; this.apliqueRegra(e); } else if (e.getName().equals("exit")) this.removaTiposNaoReferenciados(); if (e.getAttributeValue("type") != null) if (!PreDefinicoes.ehTipoPreDefinido(e.getAttributeValue("type"))) this.removaSeNecessarioListaNaoReferenciados(e); } private void removaTiposNaoReferenciados() { for (int i = 0; i < tiposNaoReferenciados.size(); i++) root.removeChildren(tiposNaoReferenciados.get(i)); } private void removaSeNecessarioListaNaoReferenciados(InterfaceElemento e) { for (int i = 0; i < tiposNaoReferenciados.size(); i++) if (tiposNaoReferenciados.get(i).getAttributeValue("name").equals( e.getAttributeValue("type"))) tiposNaoReferenciados.remove(i); } // A ordem teve que ser invertida agora pois poderiamos retirar um elemento // e alterar o caminho DOM de exclusão passado pelo usuário. // Assim, exclui-se primeiro as folhas e adapta-se as ligações. private void apliqueRegra(InterfaceElemento e) { List children = e.getChildren(); Iterator iterator = children.iterator(); while (iterator.hasNext()) { Elemento elem = (Elemento) iterator.next(); this.apliqueRegra(elem); } if ((e.getName().equals("simpleType") || e.getName().equals( "complexType")) && e.getParentElement().getName().equals("schema")) if (e.getAttributeValue("name") != null) tiposNaoReferenciados.addLast(e); boolean elementoSeraRemovido = false; for (String strRemocao : listaRemocao) if (PreDefinicoes 159 .osCaminhosDomSaoIguais(e.caminhoDOM(), strRemocao)) elementoSeraRemovido = true; if (elementoSeraRemovido) { List subCriancas = e.getChildren(); Iterator iChild = subCriancas.iterator(); while (iChild.hasNext()) { InterfaceElemento elem = (Elemento) iChild.next(); ((InterfaceElemento) e.getParentElement()).addContent(elem .clone()); } e.getParentElement().removeChildren(e); } } } package tratadores; import subetapas.AbstractSubEtapa; import ed.InterfaceElemento; import ed.Relacao; /** * @author Leo * @version 1.2 * @created 28 de Novembro de 2005 */ public class RemocaoDeTipos extends AbstractTratador { public RemocaoDeTipos(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("schema")) etapaPai.setMudanca(new Relacao("RemT", "", "", 0, 0, 0, 0)); } } package tratadores; import java.util.Iterator; import java.util.LinkedList; import java.util.List; 160 import subetapas.AbstractSubEtapa; import ed.Elemento; import ed.InterfaceElemento; import ed.PreDefinicoes; /** * @author Leo * @version 1.10 * @created 28 de Novembro de 2005 */ public class RenomeacaoDeElementosEAtributos extends AbstractTratador { private LinkedList<String> listaMudanca; private InterfaceElemento root; public RenomeacaoDeElementosEAtributos(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; root = null; listaMudanca = etapaPai.intervencaoUsuarioEspecialista("REA", "Renomeacao Elementos", ""); this.organizeLista(listaMudanca); if (listaMudanca.size() % 2 != 0) { etapaPai .mandeInformacoesInterface("ERRO NO NUMERO DE ARGUMENTOS DA REGRA RenomeacaoDeElementosEAtributos"); System.exit(1); } } /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("schema")) { root = e; this.apliqueRegra(e); } if (!documentoValido(root)) { listaMudanca = etapaPai.intervencaoUsuarioEspecialista("REA", "Renomeacao Elementos", ""); this.organizeLista(listaMudanca); if (listaMudanca.size() % 2 != 0) { etapaPai .mandeInformacoesInterface("ERRO NO NUMERO DE ARGUMENTOS DA REGRA RenomeacaoDeElementosEAtributos"); System.exit(1); } 161 this.trateElemento(root); } } private void organizeLista(LinkedList<String> lista) { int indice = 0; LinkedList<String> modificacoesAtributos = new LinkedList<String>(); while (indice < lista.size()) { if (!lista.get(indice).matches(".*->.*")) { modificacoesAtributos.addLast(lista.remove(indice)); modificacoesAtributos.addLast(lista.remove(indice)); } else indice += 2; } lista.addAll(modificacoesAtributos); } // A ordem teve que ser invertida agora pois poderiamos retirar um elemento // e alterar o caminho DOM de exclusão passado pelo usuário. // Assim, exclui-se primeiro as folhas e adapta-se as ligações. private void apliqueRegra(InterfaceElemento e) { List f = e.getChildren(); Iterator iterator = f.iterator(); while (iterator.hasNext()) { Elemento elem = (Elemento) iterator.next(); this.apliqueRegra(elem); } for (int i = 0; i < listaMudanca.size(); i += 2) { if (PreDefinicoes.osCaminhosDomSaoIguais(e.caminhoDOM(), listaMudanca.get(i))) // eh mudanca de atributo if (listaMudanca.get(i) .charAt(listaMudanca.get(i).length() - 1) == '"') { String[] mudanca = listaMudanca.get(i).split(">"); String alteracao = mudanca[mudanca.length - 1]; mudanca = alteracao.split("=", 2); mudanca[1] = mudanca[1].substring(1, mudanca[1].length() - 1); if (e.getAttributeValue(mudanca[0]).equals(mudanca[1])) { e.addAttribute(mudanca[0], listaMudanca.get(i + 1)); } 162 } // eh mudanca de nome de elemento else { String[] nameSpaces = listaMudanca.get(i + 1).split(":", 2); if (nameSpaces.length > 1) e.setNameSpace(root.getNamespace(nameSpaces[0])); } e.setName(nameSpaces[nameSpaces.length - 1]); } } private boolean documentoValido(InterfaceElemento e) { List f = e.getChildren(); Iterator iterator = f.iterator(); boolean ehValido = true; while (iterator.hasNext()) { Elemento elem = (Elemento) iterator.next(); ehValido = ehValido && this.documentoValido(elem); } if (e.getAttributeValue("name") != null) if (e.getAttributeValue("name").matches(".*Seq\\d+.*") || e.getAttributeValue("name").matches(".*Op\\d+.*")) return false; return ehValido; } } package tratadores; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedList; import subetapas.AbstractSubEtapa; import ed.Elemento; import ed.InterfaceElemento; /** * @author Leo * @version 1.6 * @created 28 de Novembro de 2005 */ public class SubstituicaoDeGruposDeElementosEAtributos extends AbstractTratador { LinkedList<InterfaceElemento> grupos; LinkedList<InterfaceElemento> referencias; public SubstituicaoDeGruposDeElementosEAtributos(AbstractSubEtapa subEtapa) { etapaPai = subEtapa; grupos = new LinkedList<InterfaceElemento>(); referencias = new LinkedList<InterfaceElemento>(); } 163 /* * (non-Javadoc) * * @see tratadores.AbstractTratador#trateElemento(ed.InterfaceElemento) */ @Override public void trateElemento(InterfaceElemento e) { if (e.getName().equals("group")) { if (e.getAttributeValue("name") != null) grupos.addLast((Elemento) e); else if (e.getAttributeValue("ref") != null) referencias.addLast((Elemento) e); } else if (e.getName().equals("exit")) this.realizeReferencias(); } private void realizeReferencias() { Hashtable<String, InterfaceElemento> groupNames = new Hashtable<String, InterfaceElemento>( 100); Iterator iterat = grupos.iterator(); while (iterat.hasNext()) { InterfaceElemento grupo = (Elemento) iterat.next(); groupNames.put(grupo.getAttributeValue("name"), grupo); grupo.getParentElement().removeChildren(grupo); } iterat = referencias.iterator(); while (iterat.hasNext()) { InterfaceElemento referencia = (Elemento) iterat.next(); InterfaceElemento troca = groupNames.get(referencia .getAttributeValue("ref")); ((InterfaceElemento) referencia.getParentElement()) .addContent(troca.clone()); referencia.getParentElement().removeChildren(referencia); } } } APÊNDICE C – Documento XSD referente a SIGMOD <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="SigmodRecord"> <xs:complexType> <xs:sequence> <xs:element name="issues"> <xs:complexType> 164 <xs:sequence> <xs:element maxOccurs="unbounded" minOccurs="0" name="issue" type="IssueType"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="IssueType"> <xs:sequence> <xs:element name="volume" type="xs:integer"/> <xs:element name="number" type="xs:integer"/> <xs:element name="articles"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" minOccurs="0" name="article" type="ArticleType"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="ArticleType"> <xs:sequence> <xs:element name="title" type="xs:string"/> <xs:element name="initial_page" type="xs:integer"/> <xs:element name="end_page" type="xs:integer"/>66 <xs:element name="authors"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" minOccurs="0" name="author" type="AuthorType"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> <xs:complexType name="AuthorType"> <xs:sequence> <xs:element name="name" type="xs:string"/> </xs:sequence> <xs:attribute name="authorPosition" type="xs:integer"/> </xs:complexType> </xs:schema> REFERÊNCIAS. ABITEBOUL, S.; BUNEMAN, P.; SUCIU, D. Data on the Web: From Relations to Semistructured Data and XML. Morgan Kaufmann, San Francisco, California, 2000. 165 GARCIA, Leonardo Gonçalves. Uma ferramenta para engenharia reversa de esquemas XML em esquemas conceituais no ambiente BInXS. Florianópolis, 2005. HALPIN, T. Business rules and object role modeling. Database Prog. and Design, v. 9,n. 10, p. 66_72, 1996. MELLO, Ronaldo dos Santos. Uma abordagem bottom-up para a integração semântica de esquemas XML. Porto Alegre, 2002. MELLO, Ronaldo dos Santos; HEUSER, Carlos Alberto. BInXS: A Process for Integration of XML Schemata.In: CAiSE 2005, Porto, Portugal, 2005. SIGMOD Record: xml version (v.1.0). Disponível em: <http://www.acm.org/sigmod/record/xml>. Acesso em nov.2008. W3C. Extensible Markup Language. Último acesso em 15 de Outubro de 2005 http://www.w3.org/XML/. W3C. W3C - OWL Overview. Último acesso em 15 de Outubro de 2005 http://www.w3.org/TR/2004/REC-owl-features-20040210/. W3C. XML Schema Definition. Último acesso em 10 de Outubro de 2005 http://www.w3.org/XML/Schema.