25 agosto, 2007

Nuevas Funcionalidades

.
Acceder a Archivos e Indices por su Alias

Cuando utilizamos recursos físicos, como ser un archivo, no es aconsejable referenciarlos directamente por su nombre real ya que éste podría cambiar y nos veríamos obligados a cambiar las referencias en nuestro código fuente.

Para evitar este problema lo recomendable es definir un alias e invocar al recurso (archivos e índices) por su alias y no por su nombre.


descriptor.xml (estracto, ilustra el uso del alias)
   1:
2: <file name="EMPLEADOS.txt" alias="EMPLEADOS" record="REmpleado">
3: <index field="nombre" alias="nombre"/>
4: <index field="legajo" alias="legajo"/>
5: <index field="sector" alias="sector"/>
6: </file>
7:

Como podemos ver agregamos al TAG <file...> el atributo alias. Esto nos permite acceder desde nuestro programa al archivo EMPLEADOS.txt sin tener que espeficar su nombre físico. También definimos alias para los índices aunque en este caso utilizamos como alias que el nombre del campo por el que indexamos.

TestAlias.java
   1:
2:package demo;
3:
4:import framework.JAFactory;
5:import framework.JAFile;
6:import framework.JAIndex;
7:
8:public class TestAlias
9:{
10: public static void main(String[] args)
11: {
12: JAFactory.getInstance().load("descriptor.xml");
13: JAFile f=JAFactory.getFileFactory().getFileByAlias("EMPLEADOS");
14:
15: // los indices fueron creados en el descriptor
16: // no hay que crearlos con createIndexOn,
17: // simplemente los tomamos y los usamos
18: JAIndex idxNom=f.getIndexByAlias("nombre");
19: JAIndex idxLeg=f.getIndexByAlias("legajo");
20: JAIndex idxSec=f.getIndexByAlias("sector");
21:
22: // ver metodos mas abajo
23: recorrerIndice(idxNom);
24: recorrerIndice(idxLeg);
25: recorrerIndice(idxSec);
26:
27: f.destroyAllIndexes();
28: f.close();
29: }
30:
31: private static void recorrerIndice(JAIndex idx)
32: {
33: idx.reset();
34: REmpleado reg=new REmpleado();
35:
36: System.out.println("--- Indice: "+idx.getAlias()+" ---");
37: while( !idx.read(reg) )
38: {
39: System.out.println(reg);
40: }
41: }
42:}
43:


Indices en varios niveles de ordenamiento

Podemos definir un índices con varios niveles de ordenamiento y en cualquier sentido: ascendente o descendente.

Por ejemplo: la cadena:
sector+direccion+nombre

Define un índice ordenado por sector, luego por dirección y luego por nombre. Siempre ascendente. En cambio la cadena:

-sector+direccion-nombre

Define que el índice será decreciente por sector, luego (a igual sector) ascendente por direccion y (a igual sector e igual direccion) decreciente por nombre.


Analicemos el descriptor donde ahora definimos diferentes criterios de indexación.

descriptor.xml (agrega índices compuestos)
   1:
2: <file name="EMPLEADOS.txt" record="REmpleado" alias="EMPLEADOS">
3: <index field="nombre" alias="nombre"/>
4: <index field="legajo" alias="legajo"/>
5: <index field="sector" alias="sector"/>
6:
7: <index field="sector+nombre+legajo" alias="CR1" />
8: <index field="-nombre+sector-legajo" alias="CR2" />
9: <index field="sector-nombre-legajo" alias="CR3" />
10: <index field="direccion-nombre" alias="CR4" />
11: </file>
12:

Para probar esto se puede utilizar el programa TestAlias.java y reemplazar los alias por CR1, CR2, etc.


IndexListener

El proceso de indexación tiene un costo: una recorrida completa al archivo. Ya que vamos a "pagar ese costo" podemos aprovechar para "meter mano" y utilizar cada uno de los registros que JAF lee mientras está indexando.

Para esto tenemos que definir una clase que implemente IndexListener, definirla como un bean dentro del <bean-factory> y relacionar el bean con el archivo que se está indexando.

Veamos nuevamente el descritor, ahora definiendo un IndexListener. Para hacerlo más claro solo dejé dos de los índices del ejemplo anterior.

descriptor.xml (define un IndexListener)
   1:
2: <file name="EMPLEADOS.txt" record="REmpleado" alias="EMPLEADOS" index-listener="MI_LISTENER">
3: <index field="sector-nombre-legajo" alias="CR3" />
4: <index field="direccion-nombre" alias="CR4" />
5: </file>
6: </driver>
7:
8: <bean-factory>
9: <bean name="MI_LISTENER" class="demo.MiIndexListener" singleton="true"/>
10: </bean-factory>
11:

Como vemos en la línea 9 definimos un bean llamado MI_LISTENER, relacionado a la clase demo.MiIndexListener y en la línea 2 relacionamos este bean al archivo EMPLEADOS.txt.

Esto hará que durante el proceso de indexación se "notifique" al listener cada vez que se lea un registro del archivo.

El próximo paso será escribir la clase MiIndexListener implementando IndexListener.

MiIndexListener.java
   1:
2:package demo;
3:
4:import java.util.Hashtable;
5:
6:import framework.util.IndexListener;
7:
8:public class MiIndexListener implements IndexListener
9:{
10: private Hashtable tablaSectores;
11:
12: // se invoca una unica vez, al principio
13: public void startProcess()
14: {
15: tablaSectores=new Hashtable();
16: }
17:
18: // se invoca varias veces, una por cada registro leido
19: public void processRecord(Object reg)
20: {
21: // casteamos al tipo de registro del archivo
22: REmpleado remp=(REmpleado)reg;
23:
24: Integer iSec=new Integer(remp.getSector());
25:
26: Integer iCont=(Integer)tablaSectores.get(iSec);
27:
28: if( iCont==null )
29: {
30: tablaSectores.put(iSec,new Integer(0));
31: }
32:
33: int cont=((Integer)tablaSectores.get(iSec)).intValue();
34: cont++;
35:
36: tablaSectores.put(iSec,new Integer(cont));
37: }
38:
39: // se invoca una unica vez, luego de haber leido
40: // el ultimo registro del archivo
41: public void endProcess()
42: {
43: // no hay nada para hacer...
44: }
45:
46: public Hashtable getTablaSectores()
47: {
48: return tablaSectores;
49: }
50:}
51:

Este listener crea un tabla de sectores con tantos contadores como sectores diferentes existen en el archivo. A medida que aparecen empleados de cada sector incrementa el contador correspondiente.

Veamos ahora el programa principal que aprovecha el listener para mostrar cuantos empleados hay por cada sector.

TestIndexListener.java
   1:
2:package demo;
3:
4:import java.util.Enumeration;
5:import java.util.Hashtable;
6:
7:import framework.JAFactory;
8:import framework.JAFile;
9:
10:public class TestIndexListener
11:{
12: public static void main(String[] args)
13: {
14: JAFactory.getInstance().load("descriptor.xml");
15: MiIndexListener listener=(MiIndexListener)JAFactory.getBeanFactory().getBean("MI_LISTENER");
16:
17: // los indices se crean una ves que pedimos el file
18: JAFile f=JAFactory.getFileFactory().getFileByAlias("EMPLEADOS");
19:
20: Hashtable t=listener.getTablaSectores();
21:
22: Integer iSec;
23: Integer iCont;
24: for(Enumeration e=t.keys(); e.hasMoreElements(); )
25: {
26: iSec=(Integer)e.nextElement();
27: iCont=(Integer)t.get(iSec);
28:
29: System.out.println("Sector: "+iSec+", "+iCont+" empleados");
30: }
31: }
32:}
33:


Ordenamiento de Archivos

JAF permite ordenar archivos aunque esto implica subir el archivo a memoria, ordenarlo y reescribirlo ordenado según el criterio especificado.

Para ordenar un archivo debemos escribir una clase que implemente la interface SortCriteria y espeficicar cual será el criterio de ordenamiento.

MiCriterio.java
   1:
2:package demo;
3:
4:import framework.util.SortCriteria;
5:
6:public class MiCriterio implements SortCriteria
7:{
8: // retorna >0 si o1 es mayor que o2
9: // retorna <0 si o1 es menor que o2
10: // retorna ==0 si o1 es igual a 02
11: public int compare(Object o1, Object o2)
12: {
13: REmpleado r1=(REmpleado)o1;
14: REmpleado r2=(REmpleado)o2;
15:
16: int difSector=r1.getSector()-r2.getSector();
17: int difNom=r1.getNombre().compareTo(r2.getNombre());
18:
19: return difSector!=0?difSector:difNom;
20: }
21:}
22:

El siguiente programa ordena el archivo EMPLEADOS.txt utilizando el criterio anterior.

TestSort.java
   1:
2:package demo;
3:
4:import framework.JAFactory;
5:import framework.JAFile;
6:
7:public class TestSort
8:{
9: public static void main(String[] args)
10: {
11: JAFactory.getInstance().load("descriptor.xml");
12: JAFile f=JAFactory.getFileFactory().getFileByAlias("EMPLEADOS");
13:
14: // ordena
15: f.sort(new MiCriterio());
16:
17: f.close();
18: }
19:}
20:






.

No hay comentarios.: