Laboratorio 0002: Gestión de Tuplas

publicado a la‎(s)‎ 6 jun. 2012 18:06 por Hernan Nina Hanco   [ actualizado el 7 may. 2013 13:08 ]
I) OBJETIVOS
  • Implementar la gestión de tuplas.

II) MARCO CONCEPTUAL


En la presente práctica, se implementa la gestión de tuplas como base para la gestión de páginas que contienen a una o varias tuplas en bloques de disco de tamaño fijo.
Dentro de la práctica, se implementa una clase Relación que es una abstracción básica de un Esquema de Relación que proporciona información de los atributos de la relación. También se implementa una Clase Atributo como parte del esquema de relación, la información que mantiene la clase Atributo, es el nombre de los atributos y los tipos de cada atributo.

Por lo tanto, podemos ahora definir las Tuplas y la Gestión de las mismas en base a la información del esquema de relación. Para este propósito, se implementa una Clase Tupla que permite representar cualquier tupla que esta compuesto por un identificador de tupla y los valores de la tupla, una tupla es un conjunto de celdas, para asegurar que esta clase Tupla represente a cualquier posibilidad de generar tuplas se implementa métodos que pueden identificar el tipo de una determinada celda de tupla. También se implementa una clase GestorIOTupla que permite escribir una tupla cualquiera en un arreglo de bytes y representar una tupla desde un arreglo de Bytes. La finalidad de trabajar las tuplas en bytes será necesario para trabajar con la gestión de paginas.   

III) PRÁCTICAS DE LABORATORIO

1) Implementar las siguientes clases, para la gestión de tuplas.
Clase Atributo
/*
 * Creado el 30 de Noviembre, 2011 por Hernán Nina Hanco
 *
 * Modificado el 11 de Diciembre, 2011 por Hernán Nina Hanco
 *
 * Esto es parte del proyecto Taqque.  
 * Código exclusivamente para fines académicos.
 * 
 * 
 * Universidad Nacional de San Antonio Abad del Cusco
 * Carrera de Ingeniería Informática y de Sistemas
 * 
 */
package org.taqque.almacenamiento;

/**
 * Atributo: Abstracción básica de un atributo como parte del 
 * modelo de datos del SGBD.
 *
 * @author hanconina
 */
public class Atributo implements java.io.Serializable {

    /** Nombre del atributo */
    private String nombre;
    /** Tipo de datos del atributo. */
    private Class<? extends Comparable> tipo;

    /**
     * Crear un nuevo atributo por su nombre y clase.
     * 
     * @param nombre, representa el nombre del atributo.
     * @param tipo, representa la clase del atributo.
     */
    public Atributo(String nombre, Class<? extends Comparable> tipo) {
        this.nombre = nombre;
        this.tipo = tipo;
    } // Atributo()
    
    /**
     * Devuelve el nombre del atributo.
     * 
     * @return nombre del atributo.
     */    
    public String getNombre() {
        return nombre;
    }
    
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    /**
     * Devuelve la clase o tipo del atributo.
     * 
     * @return tipo del atributo.
     */

    public Class<? extends Comparable> getTipo() {
        return tipo;
    }

    public void setTipo(Class<? extends Comparable> tipo) {
        this.tipo = tipo;
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (! (o instanceof Atributo)) return false;
        Atributo a = (Atributo) o;
        return getNombre().equals(a.getNombre()) && 
                getTipo().equals(a.getTipo());
    }

    @Override
    public int hashCode() {
        int hash = 17;
        hash = hash*31 + getNombre().hashCode();
        return hash*31 + getTipo().hashCode();
    }
    
    /**
     * Representación Textual.
     */
    @Override
    public String toString() {
        return getNombre() + ":" + getTipo();
    } // toString()    
}


Clase Relacion 
package org.taqque.almacenamiento; import java.util.Iterator; import java.util.List; import java.util.ArrayList; /** * * @author hernan */ public class Relacion implements java.io.Serializable, Iterable<Atributo> { /** lista de atributos de la relación. */ private List<Atributo> atributos; /** Constructor por Default de una relación. */ public Relacion() { atributos = new ArrayList<Atributo>(); } /** * Constructor de relación dado una <code>Lista</code> de atributos. * * @param atributos, atributos de la relacion. */ public Relacion(List<Atributo> atributos) { this.atributos = new ArrayList<Atributo>(atributos); } /** * Añadir un atributo a la relación. * * @param atributo, atributo a ser añadido. */ protected void adicionarAtributo(Atributo atributo) { atributos.add(atributo); } /** * Devuelve el numero de atributos de la relación. * * @return numero de atributos de una <code>Relación</code> */ public int getNumeroDeAtributos() { return atributos.size(); } /** * Devuelve un <code>Iterator</code> sobre los atributos de la * relación. * * @return <code>Iterator</code> de Atributos de la <code>Relación</code>. * */ @Override public Iterator<Atributo> iterator() { return atributos.iterator(); } /** * Devuelve un atributo especifico de la relación. * * @param i el indice del atributo que será devuelto. * @return el atributo especificaco. */ public Atributo getAtributo(int i) { return atributos.get(i); } /** * Dado el nombre de un atributo, se devuelve el índice de este atributo * en el esquema de la relación. Se devuelve <code>-1</code> si el atributo * no aparece en el esquema de la relación. * * @param atr el nombre del atributo * @return el indice del atributo en el esquema de la relación, * <code>-1</code> si el atributo no aparece en el esquema de la relación. */ public int getIndiceAtributo(String atr) { int i = 0; for (Atributo atributo : atributos) { if (atributo.getNombre().equals(atr)) { return i; } } return -1; } // getIndiceAtributo() /** * Representación textual de una relación. */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("{"); for (int i = 0; i < getNumeroDeAtributos() - 1; i++) { sb.append(getAtributo(i)).append(", "); } sb.append(getAtributo(getNumeroDeAtributos() - 1)).append("}"); return sb.toString(); } // toString() }

Clase IdentificadorTupla
package org.taqque.almacenamiento;

/**
 * Un Identificador para una Tupla
 * 
 * @author hernan
 */
public class IdentificadorTupla {

    /** Nombre de archivo al que pertenece la tupla. */
    private String nombreArchivo;
    /** Numero de la tupla. */
    private int numero;

    /**
     * Construye un nuevo identificador de tupla cuando se conoce el nombre del
     * archivo al que pertence la tupla. El numero de tupla se cambia luego
     * 
     * @param Nombre del archivo al que pertenece la tupla.
     */
    public IdentificadorTupla(String nombreArchivo) {
        this(nombreArchivo, -1);
    } 

    /**
     * Construye una nueva tupla conociendo el nombre de archivo y el numero de tupla
     * 
     * @param nombreArchivo Nombre de archivo al que pertenece la tupla.
     * @param numero Numero de la tupla.
     */
    public IdentificadorTupla(String nombreArchivo, int numero) {
        this.nombreArchivo = nombreArchivo;
        this.numero = numero;
    }

    /**
     * Devuelve el nombre del archivo al que pertenece la tupla.
     * 
     * @return nombre del archivo al que pertenece la tupla.
     */
    public String getNombreArchivo() {
        return nombreArchivo;
    } 
    

    /**
     * Devuelve el numero de la tupla.
     * 
     * @return the number of this tuple in the file.
     */
    public int getNumero() {
        return numero;
    } // getNumber()

    /**
     * Sets the number of this tuple in the file.
     * 
     * @param number the new number of this tuple in the file.
     */
    public void setNumero(int number) {
        this.numero = number;
    } // setNumber()

    /**
     * Checks two tuple identifiers for equality.
     * 
     * @param o an object to compare this identifier to.
     * @return <pre>true</pre> if the two tuple identifiers are equal
     * <pre>false</pre> otherwise.
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (!(o instanceof IdentificadorTupla)) {
            return false;
        }
        IdentificadorTupla tid = (IdentificadorTupla) o;
        return getNombreArchivo().equals(tid.getNombreArchivo())
                && getNumero() == tid.getNumero();
    } // equals()

    /**
     * Computes the hashcode of this tuple identifier.
     *
     * @return this tuple identifier's hashcode.
     */
    @Override
    public int hashCode() {
        int hash = 17;
        hash = hash * 31 + getNombreArchivo().hashCode();
        return hash * 31 + getNumero();
    } // hashCode()

    /**
     * Textual representation.
     */
    @Override
    public String toString() {
        return "[" + (getNombreArchivo() != null ? getNombreArchivo() : "")
                + " - " + getNumero() + "]";
    } // toString()
}

Clase Par 
package org.taqque.almacenamiento;

/**
 * @author hernan
 *
 * Representa un par de valores.
 */

public class Par <P, S> {
    /** El primer elemento. */
    public P primero;
    /** El segundo elemento. */
    public S segundo;


    /**
     * Constructor Default.
     */
    public Par() {
        primero = null;
        segundo = null;
    }

    /**
     * Constructor de un nuevo par conociendo su primer y segundo elemento.
     *
     * @param p el primer elemento.
     * @param s el segundo elemento.
     */
    public Par(P p, S s) {
        primero = p;
        segundo = s;
    } // Par()


    /**
     * Representación Textual.
     *
     * @return Representación textual del par.
     */
    @Override
    public String toString() {
        return "(" + (primero != null ? primero : ("null"))
            + ", " + (segundo != null ? segundo : ("null")) + ")";
    } // toString()
}


Clase Convert 
package org.taqque.almacenamiento;

/**
 * @author 
 *
 * Convert: Conversión de tipos entre tipos primitivos y arreglo de bytes
 */
public class Convert {

    public static final int INT_SIZE = 4;
    public static final int LONG_SIZE = 8;
    public static final int SHORT_SIZE = 2;
    public static final int CHAR_SIZE = 2;
    public static final int FLOAT_SIZE = 4;
    public static final int DOUBLE_SIZE = 8;
    
    public Convert() {}

    public static void toByte(int i, byte [] bytes, int o) {
        for (byte b = 0; b <= 3; b++)
            bytes[o+b] = (byte) (i >>> (3 - b)*8);
    }
    
    public static byte [] toByte(int i) {
        byte b[] = new byte[4];
        toByte(i, b, 0);
        return b;
    }

    public static void toByte(short w, byte [] bytes, int o) {
        for (byte b = 0; b <= 1; b++)
            bytes[o+b] = (byte) (w >>> (1 - b)*8);
    }

    public static byte [] toByte(short w) {
        byte b[] = new byte[2];
        toByte(w, b, 0);
        return b;
    } // toByte()

    public static void toByte(long l, byte [] bytes, int o) {
        for (byte b = 0; b <= 7; b++)
            bytes[o+b] = (byte)(int) (l >>> (7 - b)*8);
    }

    public static byte [] toByte (long l) {
        byte b[] = new byte[8];
        toByte(l, b, 0);
        return b;
    } // toByte()

    public static void toByte(char c, byte [] bytes, int o) {
        for (byte b = 0; b <= 1; b++)
            bytes[o+b] = (byte) (c >>> (1-b)*8);
    }

    public static byte [] toByte (char c) {
        byte b[] = new byte[2];
        toByte(c, b, 0);
        return b;
    }

    public static void toByte(float f, byte [] bytes, int o) {
        int i = Float.floatToIntBits(f);
        toByte(i, bytes, o);
    }

    public static byte [] toByte (float f) {  
        byte b[] = new byte[4];
        toByte(f, b, 0);
        return b;
    }

    public static void toByte(double d, byte [] bytes, int o) {
        long l = Double.doubleToLongBits(d);
        toByte(l, bytes, o);
    }

    public static byte [] toByte (double d) {
        byte [] b = new byte[8];
        toByte(d, b, 0);
        return b;
    }

    public static byte [] toByte(String s) {
        byte [] b = new byte[2*s.length()];
        toByte(s, b, 0);
        return b;
    }

    public static byte [] toByte(String s, byte [] bytes, int o) {
        int length = s.length();
        for (int i = 0; i < length; i++) {
            byte [] two = toByte(s.charAt(i));
            bytes[2*i] = two[0];
            bytes[2*i+1] = two[1];
        }
        return bytes;
    }

    public static int toInt (byte b[]) {
        return toInt(b, 0);
    }

    public static int toInt (byte b[], int o) {
        int i = 0;
        for (int b0 = 0; b0 <= 3; b0++) {
            int j;
            if (b[o+b0] < 0) {
                j = (byte) (b[o+b0] & 0x7f);
                j |= 0x80;
            }
            else {
                j = b[o+b0];
            }
            i |= j;
            if (b0 < 3) i <<= 8;
        }
        return i;
    }

    public static short toShort(byte b[]) {
        return toShort(b, 0);
    }
    
    public static short toShort(byte b[], int o) {
        short word0 = 0;
        for (int b0 = 0; b0 <= 1; b0++) {
            short word1;
            if (b[o+b0] < 0) {
                word1 = (byte)(b[o+b0] & 0x7f);
                word1 |= 0x80;
            }
            else {
                word1 = b[o+b0];
            }
            word0 |= word1;
            if(b0 < 1) word0 <<= 8;
        }
        return word0;
    }
    
    public static long toLong (byte b[]) {
        return toLong(b, 0);
    }

    public static long toLong (byte b[], int o) {
        long l = 0L;
        for (int b0 = 0; b0 <= 7; b0++) {
            long l1;
            if (b[o+b0] < 0) {
                l1 = (byte)(b[o+b0] & 0x7f);
                l1 |= 128L;
            }
            else {
                l1 = b[o+b0];
            }
            l |= l1;
            if(b0 < 7) l <<= 8;
        }
        return l;
    }
    
    public static char toChar (byte b[]) {
        return toChar(b, 0);
    }
    
    public static char toChar (byte b[], int o) {
        char c = 0;
        c = (char)((c | (char)b[o]) << 8);
        c |= (char)b[o+1];
        return c;
    }
    
    public static float toFloat (byte b[]) {
        return toFloat(b, 0);
    }
    
    public static float toFloat (byte b[], int o) {
        float f = 0.0F;
        Float float1 = new Float(f);
        int i = toInt(b, o);
        f = Float.intBitsToFloat(i);
        return f;
    }
    
    
    public static double toDouble (byte b[]) {
        return toDouble(b, 0);
    }
    
    public static double toDouble (byte b[], int o) {
        double d = 0.0D;
        Double double1 = new Double(d);
        long l = toLong(b, o);
        d = Double.longBitsToDouble(l);
        return d;
    }

    public static String toString(byte [] b) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < b.length-1; i = i+2) {
            byte [] two = new byte[2];
            two[0] = b[i];
            two[1] = b[i+1];
            sb.append(toChar(two));
        }
        return sb.toString();
    } 
    }


Clase Tupla 
package org.taqque.almacenamiento;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author hernan
 */
public class Tupla {

    /** Identificador de la tupla. */
    private IdentificadorTupla idTupla;
    /** Valores almacenados en la tupla. */
    private List<Comparable> valores;

    /**
     * Constructor de una nueva <code>Tupla</code> vácia.
     */
    public Tupla() {
        this.idTupla = null;
        this.valores = new ArrayList<Comparable>();
    } // Tupla()

    /**
     * Constructor de una nueva tupla dado un identificador y  
     * <code>Lista</code> de valores.
     * 
     * @param idTupla, identificador de la tupla.
     * @param valores el valores a ser añadidos.
     */
    public Tupla(IdentificadorTupla idTupla, List<Comparable> valores) {
        this.idTupla = idTupla;
        this.valores = valores;
    } // Tupla()

    /**
     * Devolver el identificador de la tupla.
     * 
     * @return el identificador de la tupla.
     */
    public IdentificadorTupla getIdTupla() {
        return idTupla;
    } // getIdTupla()

    /**
     * Cambiar el valor de una celda de la tupla.
     * 
     * @param celda, la celda de la tupla a la que se accede.
     * @param valor, el nuevo valor en la celda de la tupla.
     */
    public void setValor(int celda, Comparable valor) {
        valores.set(celda, valor);
    } // setValor()

    /**
     * Cambia los valores de la tupla.
     * 
     * @param valores, una lista de los valores nuevos.
     */
    public void setValores(List<Comparable> values) {
        this.valores.clear();
        this.valores = values;
    } // setValores()

    /**
     * Devuelve la cantidad de celdas de la tupla.
     * 
     * @return numero de celdas en la tupla.
     */
    public int size() {
        return valores.size();
    } // size()

    /**
     * Devuelve los valores de la tupla.
     * 
     * @return valores de la tupla.
     */
    public List<Comparable> getValores() {
        return valores;
    } // getValores()

    /**
     * Devolver la celda de una tupla como tipo primitivo character.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * character.
     * 
     */
    public char asChar(int celda) {
        Character c = (Character) valores.get(celda);
        return c.charValue();
    } // asChar()

    /**
     * Devolver la celda de una tupla como tipo primitivo Byte.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * Byte.
     * 
     */
    public byte asByte(int celda) {
        Byte b = (Byte) valores.get(celda);
        return b.byteValue();
    } // asByte()

    /**
     * Devolver la celda de una tupla como tipo primitivo Short.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * Short.
     * 
     */
    public short asShort(int celda) {
        Short s = (Short) valores.get(celda);
        return s.shortValue();
    } // asShort()

    /**
     * Devolver la celda de una tupla como tipo primitivo int.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * int.
     * 
     */
    public int asInt(int celda) {
        Integer in = (Integer) valores.get(celda);
        return in.intValue();
    } // asInt()

    /**
     * Devolver la celda de una tupla como tipo primitivo Long.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * long.
     * 
     */
    public long asLong(int celda){
        Long l = (Long) valores.get(celda);
        return l.longValue();
    } // asLong()

    /**
     * Devolver la celda de una tupla como tipo primitivo float.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * float.
     * 
     */
    public float asFloat(int celda){
        Float f = (Float) valores.get(celda);
        return f.floatValue();
    } // asFloat() 

    /**
     * Devolver la celda de una tupla como tipo primitivo double.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * double.
     * 
     */
    public double asDouble(int celda){
        Double doub = (Double) valores.get(celda);
        return doub.doubleValue();
    } // asDouble() 

    /**
     * Devolver la celda de una tupla como tipo primitivo String.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * String.
     * 
     */
    public String asString(int celda) {
        String str = (String) valores.get(celda);
        return str;
    } // asString()

    /**
     * Devolver la celda especificada de la tupla como generic
     * Comparable.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return la celda especifica de la tupla como generic Comparable.
     */
    public Comparable getValor(int celda) {
        return valores.get(celda);
    } // getValue()

    /**
     * probar la igualdad de objetos.
     *
     * @param o objeto a comparar con la tupla.
     * @return <code>true</code> si la tupla es igual a
     * <code>o</code>, <code>false</code> caso contrario.
     */
    @Override
    public boolean equals(Object o) {

        if (o == this) {
            return true;
        }
        if (!(o instanceof Tupla)) {
            return false;
        }
        Tupla t = (Tupla) o;
        if (size() != t.size()) {
            return false;
        }
        if (!getIdTupla().equals(t.getIdTupla())) {
            return false;
        }
        int i = 0;
        for (Comparable comp : valores) {
            if (!comp.equals(t.getValor(i))) {
                return false;
            }
            i++;
        }
        return true;
    }

    /**
     * Devolver el hash code de la tupla.
     *
     * @return un hash code de la tupla.
     */
    @Override
    public int hashCode() {
        int hash = 17;
        hash += 31 * hash + getIdTupla().hashCode();
        for (Comparable comp : valores) {
            hash += 31 * hash + comp.hashCode();
        }
        return hash;
    }

    /**
     * Representación Textual.
     */
    @Override
    public String toString() {
        return idTupla.toString() + " : " + valores.toString();
    } // toString()
}


Clase GestorIOTupla 
package org.taqque.almacenamiento;

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;

import org.taqque.modelo.test.Atributo;
import org.taqque.modelo.test.Relacion;

/**
 * GestorIOTupla: Se encarga de entrada y salida de una tupla 
 * para el trabajo con paginas
 *
 * @author hernan
 */
public class GestorIOTupla {

    /** relación a la que pertenecen las tuplas. */
    private Relacion relacion;
    /** El nombre del archivo de la relación. */
    private String nombreArchivo;

    /**
     * Constructor de un nuevo gestor conociendo el esquema de la relación.
     * 
     * @param relacion, es el esquema de la relación.
     * @param nombre del archivo de la relación.
     */
    public GestorIOTupla(Relacion relacion, String nombreArchivo) {
        this.relacion = relacion;
        this.nombreArchivo = nombreArchivo;
    } // GestorIOTupla()

    /**
     * Escribir una tupla a un arreglo de byte -- esto se usará cuando
     * se gestione las tuplas en las páginas.
     * 
     * @param tupla la tupla a ser escrita.
     * @param bytes el arreglo de byte de la tupla a ser escrita.
     * @param inicio el desplazamiento inicial dentro del arreglo de bytes.
     * @return un nuevo desplazamiento en el arreglo de byte, si es -1 hay
     * problemas.
     * 
     */
    public int escribirTupla(Tupla tupla, byte[] bytes, int inicio) {
        // Escribir el id de la tupla
        byte[] b = Convert.toByte(tupla.getIdTupla().getNumero());
        System.arraycopy(b, 0, bytes, inicio, b.length);
        inicio += b.length;
        // escribir los valores de la tupla a un arreglo de bytes
        b = null;

        int celda = 0;
        for (Atributo atr : relacion) {
            inicio = volcadoDeCelda(
                    atr.getTipo(), tupla, celda++, bytes, inicio);
        }

        return inicio;
    } // escribirTupla()

    /**
     * Leer una tupla de un arreglo de bytes -- se utilizara cuando se gestione 
     * las tuplas en paginas.
     * 
     * @param bytes el arreglo de bytes.
     * @param inicio inicio del desplazamiento dentro del arreglo de bytes.
     * @return un objeto par consistiendo en la tupla leida y el nuevo 
     * desplazamiento en el arreglo de bytes.
     * 
     */
    public Par<Tupla, Integer> leerTupla(byte[] bytes, int inicio) {

        // leer el id de la tupla
        byte[] b = new byte[Convert.INT_SIZE];
        System.arraycopy(bytes, inicio, b, 0, b.length);
        int id = Convert.toInt(b);
        inicio += b.length;
        List<Comparable> valores = new ArrayList<Comparable>();
        int celda = 0;
        for (Iterator<Atributo> it = relacion.iterator();
                it.hasNext(); celda++) {
            Par<? extends Comparable, Integer> par = extraer(it.next().getTipo(), bytes, inicio);
            inicio = par.segundo;
            valores.add(par.primero);
        }
        Tupla t = new Tupla(new IdentificadorTupla(nombreArchivo, id), valores);
        return new Par<Tupla, Integer>(t, new Integer(inicio));
    } // leerTupla()

    /**
     * método base para volcar una celda de tupla a un arreglo de bytes.
     * 
     * @param tipo el tipo de la celda.
     * @param t la tupla.
     * @param s la celda de la tupla a ser volcada como arreglo de bytes.
     * @param bytes el arreglo de donde la celda será volcada.
     * @param inicio el inicio de desplazamiento.
     * @return el nuevo desplazamiento en el arreglo.
     * 
     */
    protected int volcadoDeCelda(Class<? extends Comparable> tipo, Tupla t,
            int c, byte[] bytes, int inicio) {
        if (tipo.equals(Character.class)) {
            byte[] b = Convert.toByte(t.asChar(c));
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else if (tipo.equals(Byte.class)) {
            bytes[inicio] = t.asByte(c);
            return inicio + 1;
        } else if (tipo.equals(Short.class)) {
            byte[] b = Convert.toByte(t.asShort(c));
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else if (tipo.equals(Integer.class)) {
            byte[] b = Convert.toByte(t.asInt(c));
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else if (tipo.equals(Long.class)) {
            byte[] b = Convert.toByte(t.asLong(c));
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else if (tipo.equals(Float.class)) {
            byte[] b = Convert.toByte(t.asFloat(c));
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else if (tipo.equals(Double.class)) {
            byte[] b = Convert.toByte(t.asDouble(c));
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else if (tipo.equals(String.class)) {
            String st = t.asString(c);
            int len = st.length();
            byte[] b = Convert.toByte(len);
            System.arraycopy(b, 0, bytes, inicio, b.length);
            inicio += b.length;
            b = Convert.toByte(st);
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else {
            System.err.println("No soporta el tipo: " + tipo.getClass().getName());
            return -1;
        }
    } // volcadoDeCelda()

    /**
     * Método básico para leer una celda de un arreglo de byte.
     * 
     * @param tipo el tipo de la celda a leer.
     * @param bytes el arreglo de bytes como entrada.
     * @param inicio el desplazamiento inicial en el arreglo de bytes.
     * @return un par de (valor, desplazamiento) con el valor leido y el nuevo
     * desplazamiento en el arreglo de bytes.
     * 
     */
    protected Par<? extends Comparable, Integer> extraer(Class<? extends Comparable> tipo, byte[] bytes, int inicio) {
        try {
            if (tipo.equals(Character.class)) {
                byte[] b = new byte[Convert.CHAR_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                return new Par<Character, Integer>(
                        new Character(Convert.toChar(b)),
                        inicio + b.length);
            } else if (tipo.equals(Byte.class)) {
                return new Par<Byte, Integer>(bytes[inicio],
                        inicio + 1);
            } else if (tipo.equals(Short.class)) {
                byte[] b = new byte[Convert.SHORT_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                return new Par<Short, Integer>(new Short(Convert.toShort(b)),
                        inicio + b.length);
            } else if (tipo.equals(Integer.class)) {
                byte[] b = new byte[Convert.INT_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                return new Par<Integer, Integer>(new Integer(Convert.toInt(b)),
                        inicio + b.length);
            } else if (tipo.equals(Long.class)) {
                byte[] b = new byte[Convert.LONG_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                return new Par<Long, Integer>(new Long(Convert.toLong(b)),
                        inicio + b.length);
            } else if (tipo.equals(Float.class)) {
                byte[] b = new byte[Convert.FLOAT_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                return new Par<Float, Integer>(new Float(Convert.toFloat(b)),
                        inicio + b.length);
            } else if (tipo.equals(Double.class)) {
                byte[] b = new byte[Convert.DOUBLE_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                return new Par<Double, Integer>(
                        new Double(Convert.toDouble(b)),
                        inicio + b.length);
            } else if (tipo.equals(String.class)) {
                byte[] b = new byte[Convert.INT_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                inicio += b.length;
                int stLength = Convert.toInt(b);
                b = new byte[2 * stLength];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                String str = Convert.toString(b);
                return new Par<String, Integer>(str, inicio + b.length);
            } else {
                return null;
            }
        } catch (ArrayIndexOutOfBoundsException aiob) {
            return null;
        }
    } // extraer()

    /**
     * Calcular el tamaño de bytes de la tupla.
     *
     * @param t la tupla.
     * @return el tamaño de byte de la tupla.
     */
    public int byteSize(Tupla t) {
        return byteSize(relacion, t);
    }

    /**
     * Calcular el tamaño en byte de una tupla dada su relación.      
     *
     * @param rel la relación.
     * @param t la tupla.
     * @return el tamaño en byte de la tupla.
     */
    public static int byteSize(Relacion rel, Tupla t) {
        // una longitud para el id
        int size = Convert.INT_SIZE;
        int celda = 0;
        for (Atributo it : rel) {
            Class<?> tipo = it.getTipo();
            if (tipo.equals(Character.class)) {
                size += Convert.CHAR_SIZE;
            } else if (tipo.equals(Byte.class)) {
                size += 1;
            } else if (tipo.equals(Short.class)) {
                size += Convert.SHORT_SIZE;
            } else if (tipo.equals(Integer.class)) {
                size += Convert.INT_SIZE;
            } else if (tipo.equals(Long.class)) {
                size += Convert.LONG_SIZE;
            } else if (tipo.equals(Float.class)) {
                size += Convert.FLOAT_SIZE;
            } else if (tipo.equals(Double.class)) {
                size += Convert.DOUBLE_SIZE;
            } else if (tipo.equals(String.class)) {
                size += Convert.INT_SIZE + 2 * t.asString(celda).length();
            }

            celda++;
        }

        return size;
    } // byteSize()

    /**
     * Debug main.
     */
    public static void main(String args[]) {
        try {
            List<Atributo> attrs = new ArrayList<Atributo>();
            attrs.add(new Atributo("character", Character.class));
            attrs.add(new Atributo("byte", Byte.class));
            attrs.add(new Atributo("short", Short.class));
            attrs.add(new Atributo("integer", Integer.class));
            attrs.add(new Atributo("long", Long.class));
            attrs.add(new Atributo("float", Float.class));
            attrs.add(new Atributo("double", Double.class));
            attrs.add(new Atributo("string", String.class));
            Relacion rel = new Relacion(attrs);

            List<Comparable> v = new ArrayList<Comparable>();
            v.add(new Character('a'));
            v.add(new Byte((byte) 26));
            v.add(new Short((short) 312));
            v.add(new Integer(2048));
            v.add(new Long(34567));
            v.add(new Float(12.3));
            v.add(new Double(25.6));
            v.add(new String("bla bla"));
            Tupla t = new Tupla(new IdentificadorTupla("redes", 0), v);
            GestorIOTupla man = new GestorIOTupla(rel, "redes");

            java.io.RandomAccessFile raf = new java.io.RandomAccessFile("redes", "rw");

            System.out.println("writing tuple..." + t);
            byte[] bytes = new byte[1024];
            //man.escribirTupla(t, raf);
            man.escribirTupla(t, bytes, 0);
            raf.close();

            raf = new java.io.RandomAccessFile("redes", "r");
            System.out.println("reading tuple...");
            // t = man.leerTupla(bytes);
            Par<Tupla, Integer> st = man.leerTupla(bytes, 0);
            System.out.println(st);
            raf.close();
        } catch (Exception e) {
            System.err.println("Exception: " + e.getMessage());
            e.printStackTrace(System.err);
        }
    } // main()
} // GestorIOTupla


IV) TAREA:
1) Representar el esquema de la relación Esquema_Cliente = (id_cliente, nombre_cliente, direccion_cliente, telefono_cliente), donde:
id_cliente tiene dominio de valores enteros,
nombre_cliente tiene dominio de valores de cadena de caracteres,
direccion_cliente tiene dominio de valores de cadena de caracteres,
telefono_cliente tiene dominio de valores entero largo.

Seguidamente, muestre el esquema creado en pantalla. Modifique el esquema de tal manera que se añada un nuevo atributo denominado tipo_cliente con dominio de valores de tipo carácter luego muéstrelo en pantalla. Finalmente modifique nuevamente el esquema para eliminar el atributo telefono_cliente y luego muestre el esquema resultante.
2) Utilizando las Clases de Software implementado en la Gestión de Tuplas, desarrolle una aplicación para realizar cualquier Esquema de Relación, donde se pueda ingresar "n" tuplas las cuales deben ser escritas en una array de bytes y recuperadas del mismo array.
3) Implemente un gestor de Paginas donde puede almacenar tuplas de una relación en el Disco. puede considerar el tamaño de las páginas en 4k. las páginas están almacenadas en un archivo de disco.


V) REFERENCIAS BIBLIOGRÁFICAS
Comments