Tutorial do HierarchicalMap
HierarchicalMap é uma interface. Assim, qualquer um pode implementá-la. Este tutorial é baseado em BasicHierarchicalmap, uma implementação referência em Java da interfae HierarchicalMap.
Este tutorial abrange os seguintes assuntos:
(O recurso de Javascript precisa estar habilitado, no seu navegador, para permitir a visualização dos códigos utilizados nos exemplos deste tutorial)
Nível Basico
1. O Primeiro ContatoA interface HierarchicalMap é composta por três conjutos principais de métodos e alguns métodos auxiliares:
Segue abaixo o nosso primeiro código de exemplo (clássico):
HierarchicalMap map = new BasicHierarchicalMap(); map.put("Saudação", "Hello World!"); System.out.println(map.get("Saudação"));
Como pode ser visto, HierarchicalMap se comporta exatamente como um HashMap quando se utiliza uma chave simples.
2. Criação de EstruturasAgora, iremos criar uma estrutura um pouco mais complexa:
Nesta estrutura, cada círculo representa um nó (que é uma instância da HierarchicalMap), e cada retângulo representa uma folha, que pode ser qualquer objeto (como por exemplo uma instância de java.lang.String). Um nó pode conter outros nós como no caso do "Pedido" e do "Endereço", ou uma folha como no caso do "tipo", "Cidade", "Estado" e do "CEP".
O trecho de código abaixo cria uma estrutra de dados representando o diagrama acima:
//criar uma HierachicalMap contendo o primeiro endereço HierarchicalMap endereco1 = new BasicHierarchicalMap(); endereco1.put("tipo", "Fatura"); endereco1.put("Cidade", "Sta Clara"); endereco1.put("Estado", "CA"); endereco1.put("CEP", "95054"); //adiciona o endereço criado na hmap HierarchicalMap hmap = new BasicHierarchicalMap(); hmap.add("Pedido/Endereço", endereco1); //cria uma outra HierachicalMap contendo o //segundo endereço HierarchicalMap endereco2 = new BasicHierarchicalMap(); endereco2.put("tipo", "Entrega"); endereco2.put("Cidade", "São Paulo"); endereco2.put("Estado", "SP"); endereco2.put("CEP", "04717-004"); //adiciona o segundo endereço na hmap hmap.add("Pedido/Endereço", endereco2);
O método "add" possui uma outra assinatura que recebe somente a chave, sem o valor. Neste caso, uma nova instância da HierarchicalMap é criada e adicionada sob a chave. Desta forma, o segundo endereço poderia ser adicionado de forma diferente como no exemplo abaixo:
3. Recuperação dos Dados//cria uma outra HierachicalMap contendo o //segundo endereço HierarchicalMap endereco2 = hmap.add("Pedido/Endereço"); endereco2.put("tipo", "Entrega"); endereco2.put("Cidade", "São Paulo"); endereco2.put("Estado", "SP"); endereco2.put("CEP", "04717-004");
Uma vez criada a estrutra, os dados podem ser recuperadas:
System.out.println(hmap.get("Pedido/Endereço/Cidade")); System.out.println(address2.get("Estado"));
O código da Listagem acima resulta na seguinte saída:
Sta Clara SP
Note que a operação get recupera somente um item de cada vez, e no caso de possuir mais itens, o primeiro dado inserido é retornado. Assim, mesmo havendo duas cidades armazenadas na estrutura, a primeira cidade, no caso "Sta Clara", foi obtida no exemplo anterior. Por outro lado, o valor retornado para o estado foi "SP", pois a operação foi efetuada sobre o nó "endereco2". Para obter todos os itens de uma mesma chave, deve-se utilizar a operação getAll:
//exemplo utilizando getAll que retorna uma Collection //contendo objetos que possuem a mesma chave java.util.Collection val = hmap.getAll("Pedido/Endereço/Cidade"); //get the iterator to printout all the objects returned java.util.Iterator itr = val.iterator(); while(itr.hasNext()) { System.out.println(itr.next()); }
O resultado da execução do código acima será:
Sta Clara São Paulo4. Interação com Coleções
A estrutura de dados pode ser percorrida através de Iterator:
//primeiro, obtém todos os endereços java.util.Collection <HierarchicalMap> enderecos = hmap.getAll("Pedido/Endereço"); // para cada endereco em enderecos for( HierarchicalMap endereco : enderecos ) { System.out.println("Endereço"); // obter o entrySet para percorrer os nós filhos, // ou seja: Cidade, Estado e CEP java.util.Set <Map.Entry> itens = endereco.entrySet(); //imprimir o par chave valor para cada item //de endereco for(Map.Entry item : itens) { System.out.println(item.getKey() + " : " + item.getValue()); } System.out.println(); } }
A saída produzida será:
Address type : Billing City : Sta Clara State : CA ZIP code : 95054 Address type : Shipping City : São Paulo State : SP ZIP code : 04717-0045. Reestruturação do Mapa
Apesar da estrutura utilizada até então estar em conformidade com a recomendação da W3C, não conseguimos extrair a vantagem da HierarchicalMap. Informações organizadas desta maneira, não permite acessar aos dados internos de forma direta (ex. recuperar o estado do endereço de entrega). Este acesso direto, pode ser obtido através de uma pequena reestruturação na HierarchicalMap. Assim, podemos implementar um método como o que está descrito a seguir:
public static void denormalize(HierarchicalMap map, String field, String keyField) { //primeiro, remove todos os campos e //substituir por uma mapa vazia Collection col = map.removeAll(field); HierarchicalMap newMap = map.add(field); //iterar através dos campos removidos Iterator itr = col.iterator(); while(itr.hasNext()) { //para cada objeto removido, verificar se é um nó //(i.e. instance of HierarchicalMap) Object o = itr.next(); if(o instanceof HierarchicalMap) { //se sim, tenta recuperar a chave //onde o nó será adicionado Object key = ((HierarchicalMap)o) .get(keyField); if(key != null) { newMap.add(key.toString(), o); } } } }
Com o métdod acima, podemos transformar o mapa original para uma estutura como abaixo:
Agora, podemos reucperar de forma mais direta:
//executar o método denormalize para reorganizar a //estrutura da Figura 7 para Figura 8 denormalize(map,"Pedido/Endereço","tipo"); //now fetch the desiered information directly System.out.print("Estado para Entrega: "); System.out.println(map .get("Pedido/Endereço/Entrega/Estado")); System.out.print("Estado para a Faturamento: "); System.out.println(map .get("Pedido/Endereço/Fatura/Estado"));
O resultado será:
Estado para Entrega: SP Estado para a Faturamento: CA
O método abaixo consegue reoganizar o mapa, de volta para estrutura original:
public static void normalize(HierarchicalMap map, String field, String keyField) { //primeiro, remove todos os campos Collection col = map.removeAll(field); Iterator itr = col.iterator(); while(itr.hasNext()) { //para cada objeto removido, validar se é um nó //(i.e. instance of HierarchicalMap) Object o = itr.next(); if(o instanceof HierarchicalMap) { //Então, criar um novo mapa com cada item //do sub-nó. //Adicionar o novo mapa sob a chave passada como //parâmetro Iterator itr2 = ((HierarchicalMap)o).entrySet().iterator(); while(itr2.hasNext()) { Entry e = (Entry)itr2.next(); if(e.getValue() instanceof HierarchicalMap) { HierarchicalMap newMap = (HierarchicalMap)e.getValue(); //note que foi utilizado o put no lugar //do add para garantir a unicidade do //campo chave newMap.put(keyField, e.getKey()); map.add(field, newMap); } } } } }
Realmente, isto é tudo sobre HierarchicalMap. Como pode ver é tão simples como isso.
Porém, podemos aplicar esta interface em soluções mais interessantes e algumas vezes mais complexas.
Continua para Nível Intermediário