1 INLEIDING 1.1 Situering CDWriter-toestellen en CDR’s worden steeds goedkoper. Daardoor hebben veel gebruikers reeds een grote collectie zelf geschreven CD’s. Deze CD’s kunnen allerlei soorten data bevatten (audio, software, persoonlijke documenten,…). Van zodra de collectie een behoorlijke omvang aanneemt, wordt het moeilijk om snel een bepaald bestand terug te vinden.
1.2 Doelstelling Om dit probleem op te lossen is het handig om een databank bij te houden van de collectie. Het zou echter een hels karwei zijn om die databank manueel op te bouwen en te updaten. Vandaar dat het mogelijk moet zijn om de databank automatisch op te bouwen. Alle gegevens zullen worden samen gebracht in een XML-bestand. De databank zal de naam van de CD bevatten en de namen van alle bestanden die op die CD staan. Ook andere parameters, zoals de datum, zullen worden opgenomen. Vervolgens moet het mogelijk zijn voor de gebruiker om snel en eenvoudig gegevens op te zoeken in het XML-bestand. De zoekactie zal niet beperkt zijn tot de naam van het bestand, maar er zal bijvoorbeeld ook kunnen worden gezocht op datum. Om het geheel zo gebruiksvriendelijk te maken, zal uiteraard een grafische gebruikersinterface (GUI) voorzien worden. In eerste instantie hebben wij ons toegespitst op het ontwikkelen van methodes voor cdrom’s en zelfgeschreven CD’s. Daarna hebben we ook getracht om hetzelfde te doen voor audioCD’s, maar dat bleek heel wat problemen met zich te brengen. In tegenstelling tot MP3-files is bij CDA-files de informatie over artiest, titel, album,… niet uit het bestand zelf af te leiden. Daarvoor moet men via internet contact leggen met CDDB [20] die dan de gewenste informatie terugstuurt. We zijn er echter niet in geslaagd de juiste Java-classes te vinden om dit alles te kunnen implementeren. Het programma werkt wel voor audioCD’s, maar de informatie die in de CD-lijst verschijnt is niet zo relevant. Langs de andere kant, op internet zijn genoeg freeware programma’s te vinden die automatisch een databank creëren voor audioCD’s.
1
1.3 Werkwijze Java biedt veel mogelijkheden om te interageren met XML en XSLT. Tevens biedt Java ook de mogelijkheden om een GUI te bouwen. Daarom wordt alles geprogrammeerd in Java. Hiervoor hebben we gebruik gemaakt van de Java-editor JPadPro [15]. Voor het programmeren van het XML-schema en de XSLT-bestanden hebben we gebruik gemaakt van XMLSpy [6]. Daar Java en XML allebei bijzonder geschikt zijn voor webtoepassingen, is het dus ook mogelijk om dit programma eventueel uit te breiden tot een webapplicatie. Dit kan bijvoorbeeld interessant zijn voor grote onderzoekscentra met een zeer uitgebreide cdrom bibliotheek. In dat geval zou men de software en de databank op een centrale server kunnen installeren, zodat elke gebruiker (die hiervoor de permissie heeft) de databank kan bevragen. Een of meerdere administrators zou men dan kunnen aanstellen voor het updaten en onderhouden van de databank.
2
2 OPSTELLEN XML-SCHEMA 2.1 Algemeen Een XML-bestand heeft een hiërarchische of boomstructuur. Hoe wordt die structuur opgebouwd? Daarvoor moet men eerst vastleggen welke informatie men precies nuttig acht om bij te houden in de CD-lijst. Met die gegevens wordt dan een boomstructuur opgebouwd die bestaat uit ouders, kinderen, attributen,… Opdat de structuur van het XML-bestand niet zou veranderen wanneer men wijzigingen aanbrengt, wordt een XML-schema gemaakt waaraan het XML-bestand moet voldoen. Aan de hand van dit schema wordt er voor gezorgd dat het XML-bestand te allen tijde geldig en welgevormd is. [1][2][4]
2.2 Het element CD In onze CD-lijst willen we de informatie van meerdere CD’s opslaan. Hoeveel CD’s dat zullen worden, is niet op voorhand geweten. Gezien het feit het ook mogelijk moet zijn om CD’s uit de lijst te verwijderen, kan het goed zijn dat op een bepaald moment de CD-lijst leeg is en dus geen CD’s meer bevat. Op die manier komen we dus voor het element CD tot minOccurs = 0 en maxOccurs = unbounded. Voor het bevragen van de CD-lijst zal het nodig zijn om voor elke opgenomen CD een unieke verwijzing vast te leggen. Elke CD heeft wel een DOS-identificatienummer (volume serienummer), maar de uniciteit van dat nummer is niet gegarandeerd [21] en het bleek bovendien niet mogelijk om vanuit de Java-omgeving dit DOS-ID op te vragen. Welke informatie betreffende de CD kan wel vanuit Java worden opgevraagd? Het volume label en de datum waarop de CD is aangemaakt. Het volume label is echter niet altijd aanwezig of is misschien voor dezelfde soort zelfgeschreven CD’s altijd dezelfde waarde. Vandaar dat het volume label niet is opgenomen in de databank. Ook bij de datum bleken zich een paar problemen voor te doen. Met behulp van Java is het geen enkel probleem om de datum van de CD te achterhalen. Voor cd-rom’s levert dit ook geen enkel probleem. Voor zelfgeschreven CD’s echter kregen wij volgende data: 197001-01 01:00:00 of 1601-01-01 01:00:00. Deze informatie is dus ook niet zo relevant. De datum van de bestanden zelf wordt echter wel correct weergegeven, zodat er toch kan
3
worden gezocht op datum. Er is dus geopteerd om de datum van de CD wel op te nemen als parameter voor het CD-element. Om nu een unieke verwijzing voor elke CD te bekomen, zal de gebruiker zelf een naam moeten opgeven voor de CD die hij aan de lijst wil toevoegen. Achteraf is dat wel voordeliger gebleken. De gebruiker kent immers ook het ID-nummer van de CD niet, maar wel de naam die hij zelf aan de CD geeft, zeg maar de naam die de gebruiker op het CD-hoesje schrijft. Zo komen we tot 2 attributen voor het element CD, namelijk naamCD en datumCD. We willen dat deze beide attributen voor elke CD worden opgenomen. Daarom leggen we volgende eis op: use required. Op een CD kunnen allerlei soorten bestanden staan; DOC-files, EXE-files, JPG-files, MP3-files,… Gezien de sterke opmars van het internet en MP3-filesharing hebben we er voor gekozen om in dat hele gamma van soorten bestanden een opsplitsing te maken tussen MP3-files en de rest. Het element CD zal dan kinderen van het type file of van het type mp3 kunnen hebben. Voor beide elementen geldt opnieuw dat minOccurs = 0 en maxOccurs = unbounded. Want het is mogelijk dat een CD enkel gewone files bevatten of enkel MP3’s en het is ook niet op voorhand geweten hoeveel bestanden een CD bevat.
2.3 Het element file Wat is de belangrijkste informatie met betrekking tot een gewoon bestand die we willen opslaan in ons XML-bestand? De bestandsnaam en het type bestand uiteraard (DOCfile, EXE-file,…). Ook de datum waarop het bestand laatst werd gewijzigd kan interessant zijn, net als het pad (de plaats op de CD waar het bestand zich precies bevindt) en de grootte van het bestand. Op die manier verkrijgen we dus volgende kinderen voor het file-element: naam, extensie, size, lastmodified, path.
2.4 Het element mp3 Voor MP3’s ligt het iets anders. Naast de informatie die we over een gewone file kunnen opvragen, kan men uit de header van een MP3-bestand met behulp van de nodige Java-classes [18][19] ook heel veel andere informatie halen die voor dit type van bestanden wel zeer interessant zijn. De gebruiker zal immers vooral geïnteresseerd zijn in de titel van het nummer, de artiest, op welk album dit nummer terug te vinden is, de 4
grootte van het bestand, het genre en het jaar waarop het album is uitgebracht. Op die manier komt men voor het mp3-element tot volgende kinderen: naam, size, lastmodified, path, artiest, album, titel, track, genre, year.
2.5 Samenvattend Als we dan het uiteindelijke schema bekijken, dan krijgen we het volgende overzicht:
Figuur 1: XML-schema
5
Tabel 1: overzicht XML-schema
element name CD file mp3 naam extensie size lastmodified path artiest album titel track genre year attribute name naamCD datumCD
type complexType complexType complexType string string nonNegativeInteger dateTime string string string string nonNegativeInteger string integer type string dateTime
Het volledige XML-schema uitgeschreven: <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xsd:element name="CDlijst"> <xsd:complexType> <xsd:sequence> <xsd:element ref="CD" minOccurs="0" maxOccurs="unbounded"/> <xsd:element name="CD"> <xsd:complexType> <xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:element ref="file"/> <xsd:element ref="mp3"/> <xsd:attribute name="naamCD" type="xsd:string" use="required"/> <xsd:attribute name="datumCD" type="xsd:dateTime" use="required"/> <xsd:element name="file"> <xsd:complexType> <xsd:sequence> <xsd:element ref="naam"/> <xsd:element ref="extensie"/> <xsd:element ref="size"/> <xsd:element ref="lastmodified"/> <xsd:element ref="path"/> <xsd:element name="mp3"> <xsd:complexType> <xsd:sequence> <xsd:element ref="naam"/> <xsd:element ref="size"/> <xsd:element ref="lastmodified"/> <xsd:element ref="path"/>
6
<xsd:element ref="artiest"/> <xsd:element ref="album"/> <xsd:element ref="titel"/> <xsd:element ref="track"/> <xsd:element ref="genre"/> <xsd:element ref="year"/> <xsd:element name="naam" type="xsd:string"/> <xsd:element name="extensie" type="xsd:string"/> <xsd:element name="size" type="xsd:nonNegativeInteger"/> <xsd:element name="lastmodified" type="xsd:dateTime"/> <xsd:element name="path" type="xsd:string"/> <xsd:element name="album" type="xsd:string"/> <xsd:element name="artiest" type="xsd:string"/> <xsd:element name="titel" type="xsd:string"/> <xsd:element name="track" type="xsd:nonNegativeInteger"/> <xsd:element name="genre" type="xsd:string"/> <xsd:element name="year" type="xsd:integer"/>
7
3 EEN XML-BESTAND AANMAKEN OF AANPASSEN Het programma dat door de gebruiker wordt opgestart is Thesis.java (voor de broncode verwijzen we naar de cd-rom). Dit programma maakt gebruik van de Java-klasse CDLijst.class. Als het programma is opgestart, heeft de gebruiker de keuze tussen een bestaande CD-lijst te openen of een nieuwe aan te maken.
3.1 Nieuw XML-bestand aanmaken Wanneer de gebruiker kiest om een nieuw bestand aan te maken, wordt de methode doeNieuw opgeroepen. Er wordt een CDLijst-object aangemaakt (CDLijst.class). Er wordt hierbij automatisch het juiste XML-Schema aan het CDLijst-object meegegeven (zie constructor van het CDLijst-object). Vervolgens moet worden aangeduid waar men het nieuwe bestand wil opslaan en moet de bestandsnaam worden opgegeven. Er wordt gecontroleerd of het aangeduide XMLbestand nog niet bestaat en er wordt automatisch voor gezorgd dat het bestand wordt opgeslaan als een XML-bestand. Vervolgens wordt een lege CD-lijst aangemaakt (schrijfLegeDatabank) en weergegeven in het Status-tabblad (zie figuur 2).
Figuur 2: Nieuwe lege CD-lijst aangemaakt
8
Het volgende dat de gebruiker moet doen, is instellen op welke drive de CD-speler zich bevindt. Hierdoor wordt de methode doeCDStationInstellen opgeroepen. Als de gebruiker zijn keuze heeft gemaakt, wordt de drive van het CDLijst-object gewijzigd (wijzigDrive). Nu kan er een CD aan het nieuwe bestand worden toegevoegd. Hierdoor wordt de methode doeCDToevoegen opgeroepen. De gebruiker wordt gevraagd een naam op te geven voor de CD die hij aan de lijst wil toevoegen. Er wordt gecontroleerd of de naam niet reeds in de lijst voorkomt. Indien dit wel het geval is, zal de gebruiker een nieuwe naam moeten opgeven, om de uniciteit van de CD-namen te verzekeren. Er wordt ook nagekeken of de vorige stappen wel zijn gebeurd (is er een bestand geopend en is er een drive aangeduid). Indien aan alle voorwaarden is voldaan, wordt de CD aan de lijst toegevoegd, met behulp van de methode voegCDtoe die op het CDLijst-object wordt toegepast. Volgende parameters worden aan deze methode meegegeven: het XML-bestand waaraan de CD wordt toegevoegd, de drive waar de CD zich bevindt en de naam van de CD. Het XML-bestand wordt omgevormd tot een RandomAccessFile, zodat we de mogelijkheid hebben om het bestand te lezen en er in te schrijven. Er wordt gezocht naar de string (het einde van het XML-bestand). De pointer wordt voor deze string geplaatst. En op deze plaats worden de gegevens van de nieuwe CD weggeschreven. Elke CD die wordt toegevoegd, wordt dus achteraan de lijst bijgevoegd. De gegevens worden opgehaald met de methode displayFiles. In deze methode worden de verschillende mappen die zich op de CD bevinden doorlopen. Per map worden eerst de gewone files uitgelezen (checkAndDisplay) en dan de MP3-files (displayMP3). Bij deze methoden kunnen we nog het volgende opmerken. Als er strings worden ingelezen, dan wordt daar steeds eerst de methode vervangAlles op toegepast. Dit is nodig om bepaalde speciale tekens (&, <, >, ‘, \, í, ó, á, ñ) uit de tekst te halen die problemen kunnen geven, of omdat UTF ze niet (h)erkent of omdat ze in XML speciale tekens zijn die moeten worden ge-escaped als ze in gewone tekst voorkomen. Voor het weergeven van de datum is er ook een aparte methode geefDatum. Java heeft een standaardmethode lastModified. Het resultaat hiervan echter is het aantal milliseconden dat is verstreken sinds 1 januari 1970 00:00:00 GMT en de laatste keer dat het bestand werd gewijzigd. Bovendien werken we in het XML-schema met het datatype dateTime dat van de volgende vorm is: YYYY-MM-DDThh:mm:ss. Elke
9
datum moet dus volgens dat formaat worden opgenomen om een welgevormd XMLbestand te hebben. Hiervoor vinden we in Java de klasse SimpleDateFormat terug. Dan zijn er nog de MP3-files. Om aan de gegevens te geraken die we in onze databank willen opslaan, moeten we eerst een speciale Java-package installeren [18][19]. Deze package bevat verschillende klassen en methodes die het mogelijk maken om uit de header van een MP3-file de gegevens te halen waarin we geïnteresseerd zijn (artiest, album, titel, track, genre, year). Deze methodes worden dan gebruikt binnen de methode displayMP3. Ook hier worden de in alle strings de speciale tekens vervangen. Het komt ook veel voor dat sommige velden niet zijn ingevuld. In dat geval geven we een lege string mee. Als er geen fouten zijn opgetreden, is de nieuwe CD nu aan het bestand toegevoegd. In het statusvenster wordt een overzicht getoond van de huidige CD-lijst (zie figuur 3).
Figuur 3: CD toegevoegd aan nieuw bestand
10
3.2 Bestaand XML-bestand aanpassen Het kan natuurlijk ook zijn dat de gebruiker een bestaande lijst een CD wil aanpassen. In dat geval kiest men voor Openen. De methode doeOpenen wordt gestart. De gebruiker moet aanduiden welk bestand hij wil openen. De klasse Xmlfilter.class zorgt ervoor dat enkel XML-bestanden worden getoond. Het gekozen XML-bestand wordt dan ingesteld als XML-bestand van een nieuw CDLijst-object. Het pad van het ingestelde CDLijst-object en van het XML-Schema worden getoond in het Statusvenster. Nu kan de gebruiker opnieuw een CD toevoegen of verwijderen. In het geval men kiest om een CD toe te voegen, dan gebeurt hetzelfde als werd beschreven in paragraaf 3.1. Kiest men voor CD verwijderen, dan wordt de methode doeCDVerwijderen opgeroepen. De gebruiker moet de naam opgeven van de CD die hij wil verwijderen. Er wordt natuurlijk gecontroleerd of er een bestand geopend is,of dat bestand niet leeg is en of de CD die men wil verwijderen wel degelijk in de CD-lijst is opgenomen. Het XML-bestand wordt opnieuw omgezet in een RandomAccessFile. Er wordt eerst een string van de inhoud van het XML-bestand gemaakt. We onderzoeken of deze string een substring bevat met de naam van de betreffende CD. Wanneer dit zo is, beginnen we opnieuw van vooraan in het bestand telkens een nieuwe lijn te lezen en die toe te voegen aan een hulpvariabele tot dat we de CD vinden die moet worden verwijderd. We lezen nu verder, maar voegen deze lijnen niet meer toe aan de hulpvariabele, totdat we het einde van dat CD-element bereiken. De rest van het bestand dat nog volgt wordt opnieuw lijn per lijn ingelezen en toegevoegd aan de hulpvariabele. Het originele XML-bestand wordt vervolgens overschreven door het nieuwe bestand dat de te verwijderen CD dus niet meer bevat. In het status-tabblad wordt nu een overzicht weergegeven van de gewijzigde databank (zie figuur 4).
11
Figuur 4: Aangepast overzicht na verwijderen CD
12
4 BEVRAGEN XML-BESTAND 4.1 Algemeen Onze CD-databank, een XML-bestand, is hiërarchisch gestructureerd. Met behulp van XSLT is het zeer eenvoudig om een XML-bestand te transformeren naar gelijk welk tekstgebaseerd formaat. Aan de hand van templates in het XSLT-bestand kunnen we eender welke informatie uit een XML-bestand halen en transformeren naar een nieuw XML-bestand. Het is ook zeer eenvoudig om een XML-bestand te transformeren naar een HTML-bestand met behulp van een XSLT-bestand. [1][2][5] Java, althans de versie JavaTM 2 SDK, Standard Edition, version 1.4 [10][11][12] bezit bovendien een speciale klasse Transformer die het transformeren van XML-bestanden met behulp van XSLT-bestanden ondersteunt. Bovendien bezit die klasse ook enkele functies om de waarde van parameters te verwijderen en opnieuw in te stellen in een XSLT-sheet. Daarom hebben wij ervoor gekozen om voor elke zoekhandeling die we wouden voorzien een XSLT-sheet te schrijven en de bijhorende transformatie te implementeren in Java. In volgende tabel wordt een overzicht gegeven van de geïmplementeerde zoekfuncties en hun parameters: Tabel 2: overzicht XSLT-bestanden parameter
stylesheet (*.xslt)
naam albumpje OpAlbum artiestje OpArtiest ext OpExtensie soort OpGenre OpNaamBestand naamBestand naam OpNaamCD titeltje opTitel opDatumCD
waarden
opTrack
track
opYear
year
waarden
gelijk, verschillend
relatie JJJJ-MM-DDTuu:mm:ss
lastmodified
naam
* string string* *string string*string
datumCD
opLastmodified
relatie
natuurlijk getal
gelijk, verschillend, kleiner, kleiner of gelijk, groter, groter of gelijk
13
4.2 Werkwijze Verschillende velden waarop men kan zoeken bevatten tekst (album, artiest, extensie,...). Voor die velden leek het ons interessant om de zoekfunctie zodanig te implementeren dat men kan werken met wildcards. Het kan bijvoorbeeld nuttig zijn om alle bestanden te zoeken waarvan de bestandsnaam begint met een bepaalde letter, eindigt met een bepaalde substring of een opgegeven substring bevat,... Dit gebeurt met behulp van een sterretje (‘*’). De mogelijke combinaties van substrings met wildcard worden ook in tabel 2 weergegeven. Tevens kan de gebruiker kiezen of hij de bestanden zoekt die aan de zoekstring voldoen (relatie = gelijk) of dat hij die bestanden zoekt die juist niet voldoen aan de opgegeven zoekstring (relatie = verschillend). De zoekfuncties die een string kunnen bevatten, bieden bovendien de mogelijkheid om al dan niet case-sensitive te zoeken. Wanneer het zoeken niet hoofdletter gevoelig is wordt de translate-functie die XSLT standaard bevat, gebruikt om alle waarden om te zetten naar UpperCase. Het is ook mogelijk om te zoeken op datum, namelijk op de datum van de CD en op de datum waarop een bestand laatst gewijzigd werd (lastmodified). Het opgeven van de datum waarop men wil zoeken gebeurt hier door middel van zes comboboxen, zodat het onmogelijk wordt om een foute datum in te geven en automatisch heeft de datum ook het juiste formaat (JJJ-MM-DDTuu:mm:ss). Bovendien wordt hierbij ook rekening gehouden met schrikkeljaren. De mogelijke relaties zijn nu uitgebreid tot verschillend (alles behalve die datum), kleiner (vóór die datum), kleiner of gelijk (vóór die datum of op die datum), gelijk (op die datum zelf), groter (na die datum), groter of gelijk (op die datum of er na). Vervolgens kan men ook nog zoeken op het nummer van een liedje (track) en op het jaar van die MP3 (year). Deze twee velden bevatten een natuurlijk getal. Er wordt hier ook gecontroleerd of de zoekstring wel van het type integer is.. Hieronder staat een voorbeeld van zo een XSLT-sheet, meer bepaald die om te zoeken op artiest (opArtiest.xslt). <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:strip-space elements="mp3"/> <xsl:param name="artiestje">Manolo SanlucarMM <xsl:param name="relatie">verschillend <xsl:param name="isCaseSensitive">false <xsl:variable name="zoekW">
14
<xsl:if test="$isCaseSensitive='true'"> <xsl:value-of select="$artiestje"/> <xsl:if test="$isCaseSensitive='false'"> <xsl:value-of select="translate($artiestje,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/> <xsl:template match="/"> <xsl:copy> <xsl:apply-templates select="CDlijst" /> <xsl:template match="CDlijst"> <xsl:copy> <xsl:apply-templates select="CD" /> <xsl:template match="CD"> <xsl:copy use-attribute-sets="AttributenCD"> <xsl:if test="$artiestje!='*'"> <xsl:apply-templates select="mp3" /> <xsl:if test="$artiestje='*'"> <xsl:if test="$relatie='gelijk'"> <xsl:copy-of select="mp3"/> <xsl:template match="mp3"> <xsl:variable name="ditEl"> <xsl:if test="$isCaseSensitive='true'"> <xsl:value-of select="artiest"/> <xsl:if test="$isCaseSensitive='false'"> <xsl:value-of select="translate(artiest,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/> de waarde van het element dat we nu onderzoeken is (<xsl:value-of select="$ditEl"/>)--> <xsl:if test="string-length($zoekW) > string-length($ditEl)"> <xsl:if test="string-length($zoekW)-string-length($ditEl)=1"> zoekW is 1 karakter langer dan ditEl --> <xsl:if test="contains($zoekW,'*')"> <xsl:variable name="hulp"><xsl:value-of select="concat(substringbefore($zoekW,'*'),substring-after($zoekW,'*'))"/> waarde van hulp is (<xsl:value-of select="$hulp"/>)--> <xsl:if test="$relatie='gelijk'"> <xsl:if test="$ditEl = $hulp" > <xsl:copy-of select="." /> <xsl:if test="$relatie='verschillend'"> <xsl:if test="$ditEl != $hulp" > <xsl:copy-of select="." /> <xsl:if test="not(contains($zoekW,'*'))"> <xsl:if test="$relatie='verschillend'"> <xsl:copy-of select="."/>
15
<xsl:if test="string-length($zoekW)-string-length($ditEl)>1"> <xsl:comment>zoekW is minstens 2 karakters langer dan ditEl--> <xsl:if test="$relatie='verschillend'"> <xsl:copy-of select="."/> <xsl:if test="string-length($zoekW) <= string-length($ditEl)" > <xsl:if test="not(contains($zoekW,'*'))" > <xsl:if test="$relatie='gelijk'"> <xsl:if test="$ditEl = $zoekW" > <xsl:copy-of select="." /> <xsl:if test="$relatie='verschillend'"> <xsl:if test="$ditEl != $zoekW" > <xsl:copy-of select="." />
<xsl:if test="contains($zoekW,'*')"> <xsl:if test="starts-with($zoekW,'*') and string-length($zoekW) >1"> <xsl:variable name="hulp" select="substring-after($zoekW,'*')" /> <xsl:variable name="pos" select="(string-length($ditEl) - string-length($hulp)) + 1" /> <xsl:variable name="hulp2" select="substring($ditEl,$pos)" /> <xsl:if test="$relatie='gelijk'" > <xsl:if test="$hulp = $hulp2" > <xsl:copy-of select="." /> <xsl:if test="$relatie='verschillend'" > <xsl:if test="$hulp != $hulp2" > <xsl:copy-of select="." /> <xsl:if test="substring($zoekW,string-length($zoekW)) = '*' and string-length($zoekW) >1"> <xsl:variable name="hulp" select="substring-before($zoekW,'*')" /> <xsl:variable name="hulp2" select="substring($ditEl,1,string-length($hulp))" /> <xsl:if test="$relatie='gelijk'" > <xsl:if test="$hulp = $hulp2" > <xsl:copy-of select="." /> <xsl:if test="$relatie='verschillend'" > <xsl:if test="$hulp != $hulp2" > <xsl:copy-of select="." /> <xsl:if test="not(starts-with($zoekW,'*')) and substring($zoekW,string-length($zoekW)) != '*' and string-length($zoekW) >1"> <xsl:variable name="hulp1" select="substring-before($zoekW,'*')" /> <xsl:variable name="hulp2" select="substring-after($zoekW,'*')" /> <xsl:variable name="hulp3" select="substring($ditEl,1,string-length($hulp1))" /> <xsl:variable name="pos" select="(string-length($ditEl) - string-length($hulp2)) + 1" /> <xsl:variable name="hulp4" select="substring($ditEl,$pos)" /> <xsl:if test="$relatie='gelijk'" > <xsl:if test="($hulp1 = $hulp3) and ($hulp2 = $hulp4)" > <xsl:copy-of select="." /> <xsl:if test="$relatie='verschillend'" > <xsl:if test="($hulp1 != $hulp3) and ($hulp2 != $hulp4)" > <xsl:copy-of select="." />
16
<xsl:attribute-set name="AttributenCD"> <xsl:attribute name="naamCD"><xsl:value-of select="@naamCD" /> <xsl:attribute name="datumCD"><xsl:value-of select="@datumCD" />
Eerst worden drie parameters aangemaakt, in dit geval artiestje, isCaseSensitive en relatie. Ze krijgen een initialisatiewaarde mee. De eigenlijke waarden van deze parameters worden door de gebruiker ingevoerd in het Bevragen-tabblad. Vervolgens wordt een variabele zoekW aangemaakt. Als men case-sensitive wil zoeken, krijgt deze variabele gewoon de waarde van de parameter artiestje. Wil men geen rekening houden met hoofdletters en kleine letters, dan wordt alles omgezet naar hoofdletters, en dus wordt de variabele zoekW gelijk gesteld aan artiestje, maar in hoofdletters. Vervolgens wordt het XML-bestand dat getransformeerd wordt doorlopen. Eerst wordt het rootelement gekopieerd, evenals het CDlijst-element. Het resultaat moet immers opnieuw een welgevormd XML-bestand worden. Vervolgens worden de CD-elementen onderzocht. Het CD-element wordt gekopieerd met zijn attributen. Vandaar copy useattribute-sets=”AttributenCD”. De attributenset wordt onderaan de XSLT-sheet gedefinieerd. Dan wordt gekeken wat er moet gebeuren met de kinderen van het CDelement. Als de zoekstring verschilt van enkel een wildcard, dan wordt de template voor een mp3-element toegepast (we zoeken op artiest, dus enkel de mp3-files komen in aanmerking, gezien het feit dat het file-element geen element artiest bevat). Is de zoekstring wel enkel en alleen de wildcard en is de relatie bovendien gelijk dan wordt het mp3-element gewoon gekopieerd. Bekijken we nu wat er gebeurt in het eerste geval. Opnieuw wordt een variabele aangemaakt, ditEL, die gelijk wordt gesteld aan artiest (case-sensitive zoeken) of aan artiest in hoofdletters (case-insensitive zoeken). Nu kunnen we ditEl en zoekW gaan vergelijken. In het geval dat men case-sensitive wil zoeken bevatten zij dus gewoon de oorspronkelijke waarde van de parameters , in het andere geval bevatten ze beide enkel hoofdletters. Daarna worden twee gevallen bekeken:
17
•
De stringlengte van zoekW is groter dan die van ditEl.
Eerst wordt gekeken of het verschil in lengte gelijk is aan één. Dan zijn er twee mogelijkheden: de zoekstring bevat een wildcard of niet. Als er een wildcard is wordt eigenlijk het geval bekeken alsof er geen zou zijn (‘*’ betekent immres 0 of meer karakters). Indien er geen wildcard is en de relatie is verschillend dan moet het volledige element gekopieerd worden (bijvoorbeeld: zoekW = “Artist1”, relatie = “verschillend” en ditEl = “Artist”). Als het verschil goter is dan één, dan kan et in elk geval al nooit gelijk zijn, dus wordt enkel nog de relatie “verschillend” beschouwd. •
De lengte van zoekW is kleiner of gelijk aan die van ditEl.
Dan worden volgende gevallen beschouwd: -
zoekW bevat geen wildcard
-
zoekW bevat wel een wildcard
zoekW begint met ‘*’
zoekW eindigt met ‘*’
zoekW bevat ‘*’ (string*string)
Op die manier worden alle CD’s en zijn kinderen in de lijst doorlopen en onderzocht. Het resultaat is een nieuw welgevormd XML-bestand dat aan de zoekvoorwaarden voldoet.
18
De
XSLT-bestanden
om
te
zoeken
op
een
datum
(opDatumCD.xslt
en
opLastModified.xslt) gaan analoog te werk. Er word hier echter wel gewerkt met zes parameters, zodat de datum wordt opgesplitst in jaar, maand, dag, uur, minuten en seconden. Vervolgens worden de zes verschillende relaties onderzocht. Bovendien is het ook mogelijk om verschillende zoekbewerkingen na elkaar te laten uitvoeren. Stel dat we alle bestanden zoeken van het type EXE die staan op een CD waarvan de naam begint met een A en die geschreven zijn voor een bepaalde datum (zie figuur 5).
Figuur 5: Invoeren van meerdere zoekstrings
De eerste zoekbewerking onderzoekt het originele XML-bestand. De resultaten van deze query worden weggeschreven naar een nieuw XML-bestand dat volledig dezelfde structuur heeft als het originele XML-bestand. De tweede query wordt nu uitgevoerd op dit nieuwe XML-bestand. De resultaten hiervan worden opnieuw weggeschreven als een XML-bestand. Dit gaat zo verder tot alle query’s zijn afgewerkt. Uiteindelijk wordt dan het laatste XML-bestand, dat dus de resultaten van alle querys bevat, omgevormd tot een HTML-bestand (met behulp van toHTML.xslt) dat aan de gebruiker wordt getoond in het tabblad Resultaat (zie figuur 6).
19
Figuur 6: Resultaat zoekbewerking
Als de gebruiker kiest voor de optie Bevragen, wordt de methode doeCDBevragen opgeroepen. Deze methode zorgt ervoor dat de tabbladen Bevragen en Resultaat actief worden gemaakt. Op het tabblad kan de gebruiker met behulp van knoppen, keuzeboxen, een checkbox en invulvelden de gewenste zoekstrings ingeven. Deze worden gestockeerd in een vector. Vervolgens wordt de methode bevragen toegepast op het CDLijst-object. In deze methode worden de parameters vastgelegd die nodig zijn om het XML-bestand om te vormen met het juiste XSLT-bestand en de juiste zoekcriteria. Vervolgens wordt de functie transformeer opgeroepen. Hier word het originele XML-bestand getransformeerd naar een nieuw (hulp) XML-bestand (file1.xml) met de desbetreffende XSLT-sheet. Indien meerdere zoekstrings werden opgegeven dan wordt het hulpbestand getransformeerd en opgeslagen als een nieuw hulpbestand (file2.xml). Afhankelijk van het aantal zoekstrings bevindt het definitieve resultaat zich in file1.xml (oneven aantal query’s) of in file2.xml (even aantal query’s). Er wordt immers constant gewisseld tussen deze bestanden. Query 1: transformatie op origineel XML-bestand geeft file1.xml, query 2: transformatie op file1.xml geeft file2.xml, query 3: transformatie op file2.xml geeft weer file1.xml, ... Nadat alle query’s
20
zijn afgewerkt, wordt het definitieve XML-bestand omgezet naar een HTML-bestand (met toHTML.xslt) dat dan wordt getoond aan de gebruiker. Hieronder wordt toHTML.xslt weergegeven: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:strip-space elements="CD mp3 file"/> <xsl:variable name="spatie"><xsl:text> <xsl:template match="/">
CDLIJST overzicht ZOEKRESULTATEN
<xsl:apply-templates /> <xsl:template match="CDlijst"> <xsl:if test="count(CD/*) = 0" >
Er werden geen CD's of bestanden gevonden die aan de zoekvoorwaarden voldoen!
<xsl:if test="count(CD/*)>0" >
gevonden: - <xsl:value-of select="count(CD[count(file)>0 or count(mp3)>0])" /> CD's
- <xsl:value-of select="count(CD/*)" /> bestanden
<xsl:for-each select="CD"> <xsl:sort select="@naamCD" /> <xsl:if test="count(file)>0 or count(mp3)>0">
naam CD: | <xsl:value-of select="@naamCD" /> |
datum CD: | <xsl:value-of select="substring-before(@datumCD,'T')" /> <xsl:value-of select="$spatie" /><em> <xsl:value-of select="substring-after(@datumCD,'T')" /> |
aantal bestanden: | <xsl:value-of select="count(./*)" /> |
<xsl:if test="count(file) >0">
FILES
name | type | size | lastmodified | path |
<xsl:for-each select="file"> <xsl:sort select="naam" /> <xsl:value-of select="naam" /> | <xsl:value-of select="extensie" /> | <xsl:value-of select="size" /> | <xsl:value-of select="lastmodified" /> |
21
<xsl:value-of select="path" /> |
<xsl:if test="count(mp3) > 0" >
MP3's
name | size | lastmodified | path | artist | album | titel | track | genre | year |
<xsl:for-each select="mp3"> <xsl:sort select="naam" /> <xsl:value-of select="naam" /> | <xsl:value-of select="size" /> | <xsl:value-of select="lastmodified" /> | <xsl:value-of select="path" /> | <xsl:value-of select="artiest" /> | <xsl:value-of select="album" /> | <xsl:value-of select="titel" /> | <xsl:value-of select="track" /> | <xsl:value-of select="genre" /> | <xsl:value-of select="year" /> |
<xsl:template match="text()"> <xsl:value-of select="normalize-space()"/>
Eerst wordt het XML-bestand doorlopen en wordt er nagegaan of er elementen van het type file of mp3 in het bestand zitten. Als dit niet het geval is wil dat zeggen dat er geen resultaten werden gevonden voor de opgegeven zoekvoorwaarden. Werden er wel resultaten gevonden, dan wordt eerst een klein overzicht gemaakt: het aantal gevonden CD’s en het aantal gevonden bestanden wordt weergegeven. Vervolgens wordt per CD een tabel gemaakt met alle informatie van de gevonden bestanden (zie figuur 6). Om overtollige witte ruimtes te verwijderen voegen we bovenaan in het XSLT-bestand de methode <xsl:strip-space elements="CD file mp3"/> toe [12].
22
5 GRAPHICAL USER INTERFACE (GUI) Er is gekozen om de gebruiker zoveel mogelijk te begeleiden in de verschillende stadia van het bewerken en bevragen van de nieuw aangemaakte of geopende CD-lijst. De GUI bestaat uit een vast hoofdvenster, een instantie van de klasse MenuCatalogus die de Java-klasse JFrame extendeert, met daaraan gekoppeld een menubar en een aantal tabbladen. De beschikbare tabbladen zijn afhankelijk van de gemaakte keuzes in deze menubar. De verschillende manieren waarbij invoer van de gebruiker wordt verkregen (JFileChooser, JOptionPane) bieden altijd de mogelijkheid om de gekozen actie te annuleren.
Figuur 7: Getting Started
Om de gebruiker vanaf het begin op weg te helpen, is enkel het tabblad Getting Started (zie figuur 7) beschikbaar en is het ook geactiveerd. Hierin wordt via een JSplitPane het tabblad horizontaal in twee verdeeld. In het bovenste deel wordt via een boomstructuur, een JTree, een overzicht van de verschillende helponderwerpen gegeven. Het onderste deel van het tabblad Getting Started toont dan de inhoud van het in het bovenste deel van het tabblad geselecteerde deel van de JTree.
23
In dit stadium bevatten enkel de menu’s Bestand en Help beschikbare menu-items. Het ander menu, Bewerken, heeft immers nog geen betekenis daar er nog geen CD-lijst is aangemaakt of geopend.De menubar bevat de menu’s Bestand, Bewerken en Help. Het menu Bestand stelt de gebruiker in staat om een nieuwe CD-lijst aan te maken (menu-item Nieuw), een bestaande CD-lijst te openen (menu-item Openen) of om de toepassing af te sluiten (menu-item Sluiten) (zie figuur 8).
Figuur 8: Menu "Bestand"
De keuze Nieuw geeft aanleiding tot een pop-up venster van het type JFileChooser waarmee de gebruiker de directory waarin hij de nieuwe CD-lijst wil opslaan en de naam van de CD-lijst kan specifiëren (zie figuur 9). Het toevoegen van een filter aan de JFileChooser toont aan de gebruiker welke XML-bestanden er reeds bestaan in de doeldirectory zodat hij te allen tijde ervoor kan zorgen dat hij geen bestaande CD-lijst zou overschrijven. Er wordt trouwens een foutmelding gegeven mocht er in de doeldirectory al een CD-lijst bestaan met de ingegeven naam. Tevens wordt er ook voor gezorgd dat wanneer de gebruiker enkel de naam van het nieuwe XML-bestand ingeeft, dat het nieuwe bestand automatisch de extensie “.xml” krijgt.
Figuur 9: Filechooser
24
Analoog geeft de keuze Openen tot gevolg dat er een JFileChooser op het scherm verschijnt waarmee de gebruiker de CD-lijst die hij wenst te openen, kan bepalen. In beide gevallen wordt het hiermee corresponderende XML-Schema ingesteld (Het XSDbestand dat in de subdirectory XSD van de werkdirectory te vinden is). Een ander gevolg is dat het tabblad Status nu actief en beschikbaar wordt (zie figuur 4). Zowel het pad van de huidige CD-lijst (dit is dus het XML-bestand) en het XMLSchema worden in het bovenste deel van dit tabblad nu weergegeven. Het centrale deel van het tabblad toont een overzicht van de inhoud van de huidige CD-lijst. Op dit moment is er dus een CD-lijst gespecifiëerd. Bijgevolg is het logisch om de menu-items van het menu Bewerken beschikbaar te stellen (zie figuur 10). Deze mogelijkheden zijn CD Station Instellen, CD Toevoegen, CD Verwijderen en CDLijst Bevragen.
Figuur 10: Menu "Bewerken"
Het toevoegen van een of meerdere CD’s vergt nu eerst dat de gebruiker de drive instelt waar de toe te voegen CD zich bevindt (menu-item CD Station Instellen). Er verschijnt nu een pop-up boxje dat via een keuzebox de mogelijke stations weergeeft. Hiertoe behoren zowel CD-stations als floppydrives. Eens de keuze gemaakt, verschijnt het ingestelde CD-station onderaan in het tabblad Status. Via het menu-item CD Toevoegen worden de gegevens van de cd-rom (of zelfs floppy) gelezen, nadat de gebruiker de naam van de CD heeft ingegeven via een invoervenster dat op het scherm verschijnt. Er wordt een foutmelding gegenereerd (zie figuur 11) wanneer er al een CD is met dezelfde naam als de zopas ingegeven naam (uniciteit van de namen van de CD’s behorend tot een CD-lijst). De naam van de laatst toegevoegde CD wordt getoond onderaan het tabblad Status.
25
Figuur 11: Foutmelding
Het menu-item CD Verwijderen stelt de gebruiker in staat om een CD te verwijderen uit de huidige CD-lijst. De gebruiker voert hierbij de naam van de betreffende CD in. Er wordt een foutmelding gegenereerd wanneer blijkt dat de huidige CD-lijst de CD niet bevat. De naam van de laatst verwijderd CD wordt eveneens aangeduid onderaan het tabblad Status.
Figuur 12: Tabblad "Bevragen"
Het vierde menu-item van het menu Bewerken, namelijk CDlijst Bevragen, stelt de tabbladen Bevragen en Resultaat beschikbaar en activeert het tabblad Bevragen (zie figuur 12). Via een aantal keuzeboxen, eventueel een checkbox en desgevallend een invoerveld, worden de bevragingsvoorwaarden ingesteld. Via een knop wordt de
26
ingestelde voorwaarde toegevoegd aan de lijst met zoekvoorwaarden, die wordt getoond in het centrale venster. Een andere knop laat toe de lijst met voorwaarden te wissen. Wanneer de gebruiker de lijst met voorwaarden naar zijn wensen heeft ingesteld, laat een knop onderaan het tabblad het bevragingsmechanisme los op de huidige CD-lijst. Hierdoor wordt het tabblad Resultaat actief (zie figuur 13).
Figuur 13: Tabblad "resultaat"
In het bovenste venster worden nog eens de zoekvoorwaarden getoond. Het centrale tekstvenster toont de zoekresultaten. Een druk op de knop onder dit centrale venster brengt de gebruiker terug bij het tabblad Bevragen. Ten allen tijde zijn de menu-items van het Help-menu, Info en Getting Started, beschikbaar. Info doet een pop-up boxje op het scherm verschijnen met informatie over dit eindwerk. Getting Started activeert het tabblad Getting Started.
27
6 VEREISTEN EN BEPERKINGEN 6.1 Vereisten Eerste belangrijke vereiste is dat men JavaTM 2 SDK, Standard Edition, version 1.4 [9][10][11] installeert. Er wordt immers meermaals gebruikt gemaakt van klassen en functies die in vorige Java-edities nog niet geïmplementeerd zijn. De JavaTM 2 SDK, Standard Edition, version 1.4 is bedoeld voor Windows 95/98/NT 4.0/ME/XP/2000. Om grafische toepassingen te draaien is een processor van 166MHz of meer aangewezen en een fysisch RAM-geheugen van minstens 32 MB. Om 2 SDK, Standard Edition, version 1.4 te installeren is minimum 70 MB vrije schijfruimte vereist. Ook moet men de Java-package Helliker installeren [18][19]. Maar die staat op de cdrom, dus die moet in principe niet meer apart worden geïnstalleerd. Het programma is ontwikkeld in een Windows-omgeving. Er zijn geen testen gebeurd in een Linuxomgeving. Het is dus eventueel mogelijk dat zich daar problemen voordoen.
6.2 Beperkingen Er zijn bepaalde beperkingen aan het programma. Zoals reeds werd vermeld,is het programma vooral bedoeld voor cd-roms en zelfgeschreven CD’s die allerlei bestanden kunnen bevatten, ook MP3’s. Het programma werkt uiteraard ook voor audioCD’s, de informatie die hiervoor wordt opgeslagen in de CD-lijst is echter niet bijster interessant. Het gebruik van een GUI brengt wel een mindere performantie met zich. De tijdsduur om een nieuwe CD aan de XML-structuur toe te voegen, kan wel oplopen in vergelijking met de versie zonder GUI. De manier van bevragen laat enkel de doorsnedes van eigenschappen toe. Wanneer men bestanden wil die voldaan aan voorwaarde 1 of … ofvoorwaarde n dan moet men dit doen in n bevragingen.
28