/*
 *  record.java  -  Joris van Rantwijk
 *  in2026 Inleiding databeheer
 *
 *  Definitie van de recordformaten.
 */

import java.util.Date;
import java.io.RandomAccessFile;
import java.io.IOException;


/*
 *  Hier definieren we de twee recordtypen die we in de voorbeelden zullen
 *  gebruiken (medewerker en afdeling). Per recordtype wordt een Java class
 *  gedefinieerd, met daarin velden die overeenkomen met de relationele
 *  definitie van het record, en methodes voor het lezen en schrijven van het
 *  record in een file.
 *
 *  We beginnen echter met het definieren van een Record class, die als
 *  superclass voor de voorbeeld recordtypes wordt gebruikt. We gebruiken
 *  dit later om bestandsorganisaties te beschrijven zonder vooraf te weten
 *  welk recordtype gebruikt wordt.
 */

//===========================================================================
// Class Record
// Dit is de superclass voor alle recordtypes.
//===========================================================================
abstract class Record 
{
    // Sleutelwaarde van het record
    public int key;


    // Geef de omvang in bytes van het record in de file.
    // Deze is nodig voor het berekenen van de positie van records in de file.
    //-----------------------------------------------------------------------
    public abstract int getRecordlen();


    // Lees het record uit de gegeven file.
    // Geef een exceptie als er iets fout gaat bij het lezen.
    //-----------------------------------------------------------------------
    public abstract void read(RandomAccessFile f) throws IOException;


    // Schrijf het record naar de gegeven file.
    // Geef een exceptie als er iets fout gaat bij het schrijven.
    //-----------------------------------------------------------------------
    public abstract void write(RandomAccessFile f) throws IOException;


    // Vertaal een string in een reeks bytes. Het eerste byte is de lengte 
    // van de string, daarna volgen de karakters, aangevuld met nullen tot 
    // maxlen.
    // Deze functie wordt gebruikt voor het opslaan van strings in de file.
    //-----------------------------------------------------------------------
    protected static byte[] strToBytes(String s, int maxlen)
    {
        byte[] result = new byte[maxlen];
        if (s == null) { result[0] = 0; return result; }
        int i = (s.length() < maxlen) ? s.length() : maxlen - 1;
        s.getBytes(0, i, result, 1);
        result[0] = (byte) i;
        return result;
    }


    // Vertaal een reeks bytes in een string. Het eerste byte is de lengte
    // van de string, daarna volgen de karakters.
    // Deze functie wordt gebruikt voor het lezen van strings uit de file.
    //-----------------------------------------------------------------------
    protected static String bytesToStr(byte[] b)
    {
        return new String(b, 0, 1, b[0]);
    }


    // Construeer een nieuw record van het juiste type
    // Op deze manier kan een bestandsorganisatie worden geimplementeerd
    // zonder vooraf voor een bepaald record type te kiezen.
    //-----------------------------------------------------------------------
    public static Record newRecord(Class rectype)
    {
        try {
            return (Record)rectype.newInstance();
        } catch (Exception e) { 
            System.out.println(e); 
            return null;
        }
    }

}


/*
 *  Nu volgt de definitie van het recordtype 'medewerker' in de vorm
 *  van de definitie van de class Medewerker.
 *  Relationele definitie:
 *    medewerker (m#, naam, adres, plaats, geboortedatum, functie, afd#)
 */

//===========================================================================
// Class Medewerker
//
// Het recordtype 'medewerker'.
//===========================================================================
class Medewerker extends Record
{
    // De velden van Medewerker komen overeen met de velden in de
    // relationele definitie
    // m# -> key
    public String naam;
    public String adres;
    public String plaats;
    public Date geboortedatum;
    public String functie;
    public int afd;
    
    // De maximale lengte (aantal karakters) van de stringvelden moet
    // vooraf worden vastgelegd.
    final static int NAAMLEN = 25;
    final static int ADRESLEN = 25;
    final static int PLAATSLEN = 25;
    final static int FUNCTIELEN = 15;

    // Opslag van velden in de file:
    //   Integer velden in 4 bytes
    //   String velden als een byte met de string-lengte, gevolgd door
    //     een reeks bytes met de karakters van de string.
    //   Date veld als 8 byte long met daarin het aantal msec sinds 1970.
    final static int recordlen = 4 + NAAMLEN + ADRESLEN + PLAATSLEN +
                                 8 + FUNCTIELEN + 4;


    // Construeer een Medewerker met een ongeldige sleutel.
    //-----------------------------------------------------------------------
    public Medewerker() 
    { 
        key = -1;
    }

    
    // Construeer een Medewerker met de gegeven velden.
    //-----------------------------------------------------------------------
    public Medewerker(int m, String naam, String adres, String plaats,
                      Date geboortedatum, String functie, int afd)
    {
        this.key = m;
        this.naam = naam;
        this.adres = adres;
        this.plaats = plaats;
        this.geboortedatum = geboortedatum;
        this.functie = functie;
        this.afd = afd;
    }


    // Geef de omvang in bytes van het record in de file.
    //-----------------------------------------------------------------------
    public int getRecordlen() 
    { 
        return recordlen; 
    }
    
    
    // Lees een Medewerker uit de gegeven file.
    // Geef een exceptie als er iets mis gaat bij het lezen.
    //-----------------------------------------------------------------------
    public void read(RandomAccessFile f) throws IOException
    {
        byte[] t;

        // Integers kunnen direct ingelezen worden.
        key = f.readInt();

        // String velden worden eerst in een byte-array gelezen,
        // en vervolgens in een String omgezet.
        t = new byte[NAAMLEN];
        f.readFully(t);
        naam = bytesToStr(t);

        t = new byte[ADRESLEN];
        f.readFully(t);
        adres = bytesToStr(t);

        t = new byte[PLAATSLEN];
        f.readFully(t);
        plaats = bytesToStr(t);

        // De datum veld wordt eerst als long gelezen, en daarna
        // omgezet in een datum.
        geboortedatum = new Date(f.readLong());

        t = new byte[FUNCTIELEN];
        f.readFully(t);
        functie = bytesToStr(t);

        afd = f.readInt();
    }

    
    // Schrijf een Medewerker naar de gegeven file.
    // Geef een exceptie als er iets mis gaat bij het schrijven.
    //-----------------------------------------------------------------------
    public void write(RandomAccessFile f) throws IOException
    {
        // Integer velden kunnen direct geschreven worden.
        f.writeInt(key);

        // String velden worden eerst omgezet in een reeks bytes.
        f.write(strToBytes(naam, NAAMLEN));

        f.write(strToBytes(adres, ADRESLEN));

        f.write(strToBytes(plaats, PLAATSLEN));

        // De datum wordt omgezet in een long en daarna geschreven.
        if (geboortedatum == null) f.writeLong(0);
        else f.writeLong(geboortedatum.getTime());

        f.write(strToBytes(functie, FUNCTIELEN));

        f.writeInt(afd);
    }


    // Geef een string met alle gegevens uit het record.
    // Hiermee kan het record straks handig op het scherm worden gezet.
    //-----------------------------------------------------------------------
    public String toString()
    {
        return
            "m#: " + key + "\n" +
            "naam: " + naam + "\n" +
            "adres: " + adres + "\n" +
            "plaats: " + plaats + "\n" +
            "geboortedatum: " + geboortedatum + "\n" +
            "functie: " + functie + "\n" +
            "afd: " + afd + "\n";
    }

}


/*
 *  De definitie van het recordtype 'afdeling' is analoog aan die van
 *  'medewerker'.
 *  Relationele definitie:
 *    afdeling (afd#, afdnaam, telefoon, locatie, budget)
 */

//===========================================================================
// Class Afdeling
//
// Het recordtype 'afdeling'.
//===========================================================================
class Afdeling extends Record
{
    // De velden van Afdeling komen overeen met de velden in de
    // relationele definitie
    // afd# -> key
    public String afdnaam;
    public String telefoon;
    public String locatie;
    public int budget;
    
    // De maximale lengte (aantal karakters) van de stringvelden moet
    // vooraf worden vastgelegd.
    final static int NAAMLEN = 25;
    final static int TELLEN = 15;
    final static int LOCATIELEN = 15;

    final static int recordlen = 4 + NAAMLEN + TELLEN + LOCATIELEN + 4;


    // Construeer een Afdeling met een ongeldige sleutel.
    //-----------------------------------------------------------------------
    public Afdeling() 
    { 
        key = -1;
    }

    
    // Construeer een Afdeling met de gegeven velden.
    //-----------------------------------------------------------------------
    public Afdeling(int afd, String afdnaam, String telefoon, 
                      String locatie, int budget)
    {
        this.key = afd;
        this.afdnaam = afdnaam;
        this.telefoon = telefoon;
        this.locatie = locatie;
        this.budget = budget;
    }


    // Geef de omvang in bytes van het record in de file.
    //-----------------------------------------------------------------------
    public int getRecordlen() 
    { 
        return recordlen; 
    }
    
    
    // Lees een Afdeling uit de gegeven file.
    // Geef een exceptie als er iets mis gaat bij het lezen.
    //-----------------------------------------------------------------------
    public void read(RandomAccessFile f) throws IOException
    {
        byte[] t;

        key = f.readInt();

        t = new byte[NAAMLEN];
        f.readFully(t);
        afdnaam = bytesToStr(t);

        t = new byte[TELLEN];
        f.readFully(t);
        telefoon = bytesToStr(t);

        t = new byte[LOCATIELEN];
        f.readFully(t);
        locatie = bytesToStr(t);

        budget = f.readInt();
    }

    
    // Schrijf een Afdeling naar de gegeven file.
    // Geef een exceptie als er iets mis gaat bij het schrijven.
    //-----------------------------------------------------------------------
    public void write(RandomAccessFile f) throws IOException
    {
        f.writeInt(key);
        f.write(strToBytes(afdnaam, NAAMLEN));
        f.write(strToBytes(telefoon, TELLEN));
        f.write(strToBytes(locatie, LOCATIELEN));
        f.writeInt(budget);
    }


    // Geef een string met alle gegevens uit het record.
    // Hiermee kan het record straks handig op het scherm worden gezet.
    //-----------------------------------------------------------------------
    public String toString()
    {
        return
            "afd#: " + key + "\n" +
            "afdnaam: " + afdnaam + "\n" +
            "telefoon: " + telefoon + "\n" +
            "locatie: " + locatie + "\n" +
            "budget: " + budget + "\n";
    }

}

//===========================================================================
// End
//===========================================================================

Generated by Java2Html