/*
* 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
//===========================================================================