Bachelorproef
Studiegebied Handelswetenschappen en Bedrijfskunde Bachelor Toegepaste Informatica Afstudeerrichting Academiejaar 2014-15 Student Martelé Lorenzo
Thema
Bouwen van een Harvesting & Indexing Toolkit (HIT) voor EurOBIS Waarom worden IPT's en HIT's gebruikt om data te verspreiden tussen onderzoekscentra?
Stageplaats
Vlaams Instituut voor de Zee Wandelaarkaai 7, 8400 Oostende
Lorenzo Martelé VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT
Lorenzo Martelé VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT
Woord vooraf Toen ik mij aanmeldde bij het Vlaams Instituut voor de Zee , dacht ik een ander stageonderwerp te krijgen. Oorspronkelijk lagen er 13 weken zwaar programmeerwerk in het verschiet, maar nadat Mr. Vanhoorne mijn CV had bekeken, kreeg ik een ander voorstel toegespeeld. De nadruk van de stage verschoof van zwaar programmeren meer naar een databank gerelateerde kwestie. Ik dank in de eerste plaats Mr. Vanhoorne en Mr. Sourie uit Howest dat ik de mogelijkheid kreeg om dit voorstel uit te werken. Verder wil ik ook de werknemers uit het VLIZ bedanken voor hun hulp. Door hun feedback kon ik een applicatie afleveren waar ik tevreden over ben. Het stagevoorstel van Mr. Vanhoorne sprak me meer aan en lag meer in de lijn van mijn kennis. Dat is de reden waarom ik voluit voor deze opdracht ben gegaan. Ik had al snel wat ideeën om een werkende applicatie te kunnen afleveren. Tenslotte mag ik niet vergeten dat dit stageproject mij heeft aangezet tot mijn onderzoeksvraag. Tijdens mijn stage vroeg ik me af waarom CSV bestanden werden gebruikt om data te verspreiden, terwijl iedere databank waarmee ik moest werken bestond uit een MSSQL databank. Het leek me overbodig om de data op een andere manier te verspreiden Het stageproject heeft mijn zienswijze over het verspreiden van data volledig veranderd.
Lorenzo Martelé VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT
Samenvatting Voor mijn stage in het Vlaams Instituut voor de Zee heb ik een nieuwe Harvesting & Indexing Toolkit (HIT) moeten maken. Eén van de redenen dat er een nieuwe HIT nodig was, was vooral omdat de oude HIT niet meer aan de wensen voldeed. De HIT was statisch, traag en verouderd. Een HIT krijgt als input DarwinCore Archives. Deze archives worden gegenereerd door een Integrated Processing Toolkit (IPT). Deze vorm van dataverspreiding heeft me aangezet tot mijn onderzoeksvraag. In de loop van dit document gaan we dieper in op IPT’s, HIT’s en het verloop van mijn stage.
Sleutelwoorden: IPT, DarwinCore Archive, HIT
Lorenzo Martelé VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT
Abstract During my internship for VLIZ, I had to create a new Harvesting & Indexing Toolkit (HIT). One of the main reasons why there was a need for a new HIT, was because the old HIT didn’t meet the expectations. It was static, slow and not up to date. A HIT receives a DarwinCore Archive. These archives are generated by an Integrated Processing Toolkit (IPT). The usage of this type of sending data inspired me to formulate my research question. While reading this document, we will elaborate more on IPT’s, HIT’s and the progress of my internship.
Key words: IPT, DarwinCore Archive, HIT
Lorenzo Martelé VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT
Verklarende woordenlijst IPT: Integrated Processing Toolkit: Een programma die data transformeert en de data op een meer leesbare manier verspreidt. HIT: Harvesting & Indexing Toolkit: Een programma, vaak uniek aan het bedrijf, die de output van een IPT inleest en verwerkt naar de wensen van het bedrijf. DarwinCore Archive: Een van de outputs die de IPT maakt. Dit is een zip bestand met een metafile en een datafile. Symfony framework: een licht PHP framework die heel wat functionaliteit voorziet, die standaard niet aanwezig is in PHP. Het framework is ook makkelijk uitbreidbaar met behulp van bundles. GBIF: Global Biodiversity Information Facility, een organisatie die de originele HIT heeft gemaakt. OBIS: Ocean Biogeographic Information System, een organisatie die samenwerkt met GBIF, maar zich enkel focust op marien leven. Een werknemer van het VLIZ heeft voor hen de GBIF HIT bijgewerkt om beter te werken met marien leven. Bulk Insert: Meer dan één record tegelijk toevoegen aan een databank. Dependency issue: Een coderingsprobleem waarbij code gebruik probeert te maken van niet-bestaande code van derden. Dependency call: Dit gebeurt als code zich baseert op code van derden. Refactoring: Een programmeerterm waarbij oude code wordt herbekeken en al dan niet wordt herschreven. Harvesting: Data ophalen uit databronnen die voorzien zijn van derden. cURL: Een applicatie die een bibliotheek en commando tool voorziet om data te ontvangen. Deze tool ondersteunt verschillende protocols. Truncated error: Een fout die een databank oproept als een te lange string wordt ingegeven in een veld. STRUTS: een open-source webapplicatie framework om Java EE web applicaties te ontwikkelen.
Lorenzo Martelé VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT
Inhoudsopgave 1
Voorstelling van het bedrijf ............................................................................... 9
2
Onderzoeksvraag............................................................................................. 10
3 3.1 3.1.1 3.1.2 3.1.2.1 3.1.2.2 3.1.2.3 3.2 3.2.1 3.2.2 3.2.2.1 3.2.2.2 3.2.2.3 3.2.2.4 3.2.2.5 3.3
Analyse............................................................................................................. 11 IPT..................................................................................................................... 11 Wat is een IPT ................................................................................................... 11 Waarom gebruik maken van een IPT ................................................................. 11 Voordelen .......................................................................................................... 11 Nadelen ............................................................................................................. 12 Alternatieven...................................................................................................... 12 HIT .................................................................................................................... 13 Wat is een HIT ................................................................................................... 13 Mogelijkheden voor HIT implementatie in het VLIZ ............................................ 13 GBIF code ......................................................................................................... 13 OBIS code ......................................................................................................... 14 Script maken...................................................................................................... 15 Bestaand project ................................................................................................ 15 PHP project (Symfony framework) ..................................................................... 15 Conclusie ........................................................................................................... 15
4 4.1 4.1.1 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.2 4.3 4.3.1 4.3.2 4.3.3 4.3.4
Ontwikkeling .................................................................................................... 16 Fases ................................................................................................................ 16 PHP applicatie ................................................................................................... 16 Symfony en GUI ................................................................................................ 16 Doctrine ............................................................................................................. 17 Logging.............................................................................................................. 17 Testing............................................................................................................... 17 Gebruiksvriendelijkheid ...................................................................................... 17 Problemen ......................................................................................................... 18 Codevoorbeelden .............................................................................................. 19 Extracting .......................................................................................................... 19 FileHandler ........................................................................................................ 20 FootprintWKT .................................................................................................... 21 Command .......................................................................................................... 22
5 5.1 5.2
Bespreking van het project ............................................................................. 23 Project ............................................................................................................... 23 Werking van de applicatie .................................................................................. 24
6
Kritische reflectie............................................................................................. 25
7
Conclusies ....................................................................................................... 26
8
Bronnen- & literatuurlijst................................................................................. 27
9
Overzicht van de bijlagen................................................................................ 28
Bijlage 1: Curl code .............................................................................................................. 29 Bijlage 2: Extracting code .................................................................................................... 30 Bijlage 3: Reading file code.................................................................................................. 32 Bijlage 4: Processing FootprintWKT code ............................................................................ 34
Lorenzo Martelé VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT
Bijlage 5: Command code .................................................................................................... 36 Bijlage 6: Startpagina ........................................................................................................... 37 Bijlage 7: Dataset pagina ..................................................................................................... 38 Bijlage 8: Dataprovider pagina ............................................................................................. 39 Bijlage 9: Dataprovider toevoegen pagina............................................................................ 40
Lorenzo Martelé
¬9
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Voorstelling van het bedrijf
1 Voorstelling van het bedrijf Het Vlaams Instituut voor de Zee vzw (VLIZ) is uitgegroeid tot een coördinatie- en informatieplatform voor zeewetenschappelijk onderzoek in Vlaanderen. Als knooppunt voor marien en kustgebonden onderzoek, fungeert het VLIZ als een partner in projecten en netwerken. Zo bevorderen en ondersteunen ze de internationale uitstraling van het Vlaams zeewetenschappelijk onderzoek en het internationaal marien onderwijs. Enkele kernactiviteiten van het VLIZ zijn:
Het faciliteren van een netwerk van mariene wetenschappers en andere betrokkenen (door aanbieden van een platform, bijdragen aan projecten, bijeenkomsten organiseren, publicaties uitgeven, ...) Huisvesten en ondersteunen van internationale organisaties. Zeewetenschappelijk onderzoek ondersteunen door het inzetten van het onderzoeksschip Simon Stevin. Beheren en uitbouwen van het VLIZ-datacentrum. Beheren van de VLIZ-bibliotheek. Beheren van een informatieloket dat objectieve wetenschappelijke informatie verstrekt aan vragende partijen. Ondersteunen van een duurzaam en wetenschappelijk onderbouwd beleid voor de kustzone, de zeegebieden en de aanpalende estuaria. Inclusief het instaan voor de productie van het ‘Compendium voor Kust en Zee’.
Lorenzo Martelé
¬ 10
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Onderzoeksvraag
2 Onderzoeksvraag Waarom worden IPT's en HIT's gebruikt om data te verspreiden tussen onderzoekscentra? In het huidige informatica tijdperk bestaan er duizenden manieren om data te verspreiden. In het Vlaams Instituut voor de Zee wordt data verspreid met behulp van CSV-files, die gegenereerd wordt door een IPT programma. De manier waarop data wordt aangeboden is op voorhand bepaald en dus niet te wijzigen. Het HIT programma die wordt gebruikt om deze data te verwerken daarentegen wel. Tijdens mijn stage in het VLIZ kreeg ik enkele mogelijkheden voorgeschoteld om een HIT te maken, die voldeed aan de wensen van het VLIZ. De aangeboden opties waren: 1) Werken met de bestaande GBIF code 2) Werken met de OBIS code (een reeds gewijzigde versie van GBIF code) 3) De data harvesten (CSV-files), de output door een script runnen om deze aan te passen aan de databank van Eurobis. 4) Werken met vernieuwde PHP code, geschreven door Robin Houthoofdt (werknemer VLIZ) 5) Zelf een programma van het begin opbouwen in PHP (Symfony framework). De uiteindelijke keuze was zelf een nieuwe applicatie bouwen in PHP, licht gebaseerd op de reeds bestaande code, gemaakt door Robin Houthoofdt.
Lorenzo Martelé
¬ 11
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Analyse
3 Analyse Mijn analyse voor deze onderzoeksvraag zal uit twee delen bestaan. Enerzijds een analyse waarom een IPT gebruikt wordt om data deels te verwerken en voor te bereiden om gedeeld te worden met de verschillende vragende partijen. Anderzijds een analyse waarom ik gekozen heb voor de huidige implementatie van een HIT.
3.1 IPT 3.1.1 Wat is een IPT IPT is de afkorting voor een Integrated Processing Toolkit. Dit betekent dat een IPT een programma is dat data ontvangt van verschillende bronnen (voorbeeld: onderzoekscentra, individuele wetenschappers, databases met gelijkaardige data, …). Deze data wordt vervolgens verwerkt door het programma, zodat deze een vooraf afgesproken structuur terug geeft aan de gebruikers. Op mijn stage werd gewerkt met de DarwinCore Archive structuur. In essentie houdt deze structuur in dat een zip-bestand met een datafile (CSV-bestand), een metafile en een emlfile (beide XML bestanden) werd gegenereerd. 3.1.2 Waarom gebruik maken van een IPT In de komende onderdelen zullen we onderzoeken waarom een DarwinCore Archive de voorkeur geniet om data te verspreiden. 3.1.2.1 Voordelen De voordelen bij het gebruik van een DarwinCore Archive is vooral de datacompressie. Door gebruik te maken van een CSV bestand kun je veel data heel compact opslaan. Als voorbeeld: Een DarwinCore Archive met meer dan 63000 records heeft een normale grootte van 30,3 megabyte, na compressie is dit nog maar 667 kilobyte. Flexibiliteit van de opslagvorm is ook een groot voordeel. Door gebruik te maken van het CSV bestand, in combinatie met een aangepaste HIT, kunnen verschillende onderzoekcentra / databases data inlezen en implementeren, die enkel noodzakelijk is voor hen. Verder is er ook geen voorkennis nodig van het IPT programma om de data te kunnen aanspreken. Een ander voordeel is de diversiteit. Heel wat programma’s kunnen, zonder grote voorkennis van die programma’s, CSV bestanden openen. Enkele voorbeelden zijn Excel, kladblok, SQL (bulk inserts), … Voor mensen die een HIT moeten programmeren is wat voorkennis vereist om CSV bestanden juist in te lezen en te gebruiken in een eigen programma. Maar voor onderzoekers die deze data willen inkijken en niet beschikken over de kennis of niet in het bezit zijn van gespecialiseerde software om de bestanden in te lezen, zijn er zoveel alternatieven om toch de data te kunnen bekijken en lezen.
Lorenzo Martelé
¬ 12
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Analyse
3.1.2.2 Nadelen Het grootste nadeel van een DarwinCore Archive, en ieder CSV bestand, is het missen van controle op de inhoud. Data die onderzoekers opmaken en die doorgegeven wordt aan het IPT programma wordt niet gecontroleerd door het IPT programma zelf. Er wordt van de onderzoekers verwacht zich te houden aan een voorkeurstructuur, maar verplichtingen zijn er niet. Hierdoor kunnen bepaalde verwachte datastructuren (voorbeeld: een datum) op veel verschillende manieren worden ingegeven of er kan zelfs een verkeerde datastructuur worden meegegeven (voorbeeld: er wordt een getal verwacht en je krijgt tekst). Deze controles worden dan verwacht in een HIT, maar hierdoor kan er wel data verloren gaan omdat de ene HIT anders kan omgaan met bepaalde data in vergelijking met een andere HIT. 3.1.2.3
Alternatieven
In het huidige informaticatijdperk zijn er heel veel manieren om data te delen met anderen. De ene is handiger om data te verwerken dan de andere. Waarom werd er gekozen voor een CSV bestand in plaats van de zoveel andere mogelijkheden? Welke andere mogelijkheden zijn er? Het alternatief die ik onder de loep zal nemen zijn SQL bestanden. Als de data verspreid zou worden in de vorm van SQL bestanden, zou je vanaf de bron al controles kunnen uitvoeren. Op deze manier werk je dus het grootste nadeel tegen van een CSV bestand. Maar de negatieve punten van een SQL bestand gebruiken is een lange lijst. Enkele grote nadelen zijn: 1) Het verplichten van een dataopslag. De SQL syntax is anders dan MySQL of andere databank alternatieven. De vragende partijen die een SQL databank gebruiken, kunnen de data zonder probleem implementeren. De anderen zouden het volledig bestand moeten hermaken om van toepassing te zijn in hun datastructuur 2) Er ontstaat een vaste structuur. Om het SQL bestand te kunnen inlezen, moet je al een databank hebben met dezelfde structuur als het bestand voordat je specifieke data eruit kunt halen. 3) Bestandsgrootte kan oplopen en dus kan er veel meer netwerkverkeer optreden als je veel en/of grote bestanden moet downloaden. 4) Er zijn specifieke programma’s en voorkennis vereist. Niet iedere onderzoeker die de data wil inkijken kan werken met een databankprogramma.
Lorenzo Martelé
¬ 13
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Analyse
3.2 HIT 3.2.1 Wat is een HIT Hit is de afkorting voor een Harvesting & Indexing Toolkit. In essentie is dit een programma die data bestanden inleest, data transformeert en vervolgens indexeert. In het geval van het VLIZ werd data ingelezen vanuit een DarwinCore Archive, vervolgens werd de data getransformeerd naar de wensen van de Eurobis Databank om tenslotte te worden ingegeven in de Eurobis Databank. Een HIT is vaak een programma dat uniek is voor iedere vragende partij. De reden hiervoor is omdat niet alle data die aanwezig is in de DarwinCore Archive nuttig is voor de vragende partij. 3.2.2 Mogelijkheden voor HIT implementatie in het VLIZ 3.2.2.1
GBIF code
GBIF, Global Biodiversity Information Facility, is een organisatie die de originele HIT heeft ontwikkeld. Het einddoel is de code aanpassen naar de wensen van het VLIZ. De code moet in staat zijn om automatisch DarwinCore Archives te harvesten en toe te voegen aan de EurOBIS databank. Na het uitpakken van de code duiken er al snel problemen op. De code is zwaar verouderd en kampt dus met codefouten dankzij verouderde imports en dependency issues. De code is dus van het begin al niet testbaar voor fouten in datatransformatie. De eerste problemen zijn de dependency issues. De code waar het programma zich op baseert, wordt niet meer ondersteund. De code werd offline gehaald van de originele download locatie. De oplossing is de code van andere locaties downloaden om tenslotte de code te kopiëren in het programma. Vervolgens moet je nog de dependency calls uit de juiste file halen. Als deze dependency zich baseert op andere code, die ook niet meer beschikbaar is, mag je de cyclus herhalen. Het tweede probleem zijn de codefouten en verouderde imports. Er zijn enkele syntax fouten opgedoken en enkele verouderde imports. Deze waren snel te verhelpen. Het probleem met de code is dat deze verouderd is, de laatste actieve wijziging dateert van augustus 2013. Voor een beter programma zou alles op de laatste versies moeten kunnen werken. Momenteel is het programma getest op verouderde versies van tomcat en MySQL (tomcat 6.0 en MySQL 5.6). Er zijn dus twee stappen om de code te verbeteren. In de eerste stap moet de code aangepast worden aan de laatste versies (Struts, JSP, ...). Ideaal kan de code dan ook refactored en aangepast worden aan betere best-practices. Een positief gevolg van de refactoring is het automatische oplossen van de verouderde imports. In de tweede stap moet deze dan ook getest worden op de laatste versies van Tomcat en MySQL.
Lorenzo Martelé
¬ 14
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Analyse
Het derde probleem zijn de security issues. Op de website waar de code af te halen is, spreken ze over een security issue met Struts2. Deze issue is ter sprake gekomen eind 2013 en er zijn geen plannen om de code nog te updaten met een oplossing. Als je inbreuken wilt voorkomen, wordt aangeraden dat de code achter een beveiligde firewall blijft en niet online beschikbaar wordt gesteld. Een oplossing voor dit probleem is de code zelf aan te passen om te werken met de laatste versie van Struts2. Om de code te beveiligen, moet de laatste versie van Struts gebruikt worden. In de laatste versie van Struts zijn enkele prefixes uit de code gehaald. Om dezelfde werking te behouden, zou een deel van de code moeten herschreven worden in combinatie met navigatie regels. Pas als de bovenstaande problemen verholpen zijn, kunnen we beginnen met het uitbreiden van het programma naar de wensen van het VLIZ. Het belangrijkste hier is de automatisering, want momenteel werkt het programma volledig manueel. Om alles te automatiseren moet er nieuwe code toegevoegd en getest worden. Tenslotte is er nog één probleem, de EurOBIS databank maakt gebruik van MSSQL. De output van het programma zou een MySQL databank zijn. Omdat de applicatie in java is gemaakt, blijft de output een MySQL databank. De oplossing is een script schrijven dat de MySQL databank vertaalt naar MSSQL. Deze optie implementeren in de tijd die voorzien is, is onmogelijk. Programmeren vanaf nul is hierbij een minder tijdrovende oplossing. Zo kun je meteen de nieuwe best-practices implementeren, kun je programmeren in een taal die compatibel is met MSSQL. Omdat je opnieuw begint, is er een kleinere kans dat er iets over het hoofd wordt gezien. 3.2.2.2
OBIS code
Een tweede mogelijkheid, is de OBIS code bijwerken naar de wensen van het VLIZ. Deze code is nog steeds geschreven in java, maar is meer object georiënteerd geprogrammeerd. Hierdoor is de code ook duidelijker leesbaar dan de GBIF code. Deze code is gebaseerd op de GBIF code (vooral het harvesting gedeelte). De OBIS code is wel specifieker geprogrammeerd voor het VLIZ. De focus van het programma is verschoven van alle gebieden naar mariene gebieden. Na het uitpakken van de code zijn er ook hier terug heel wat dependency issues. Een deel is op te lossen, maar helaas zijn er ook dependencies die niet meer bestaan en dus zou deze code moeten herschreven worden. Deze code heeft ook minder functionaliteit dan de GBIF code, omdat de OBIS code niet indexeert. Er moet dus nog steeds een indexing gedeelte geprogrammeerd worden en deze moet goed samenwerken met de bijgewerkte OBIS code. Vervolgens moet het automatiseringsproces ook nog steeds geprogrammeerd worden, want de OBIS code kan de output nog steeds niet automatisch toevoegen aan de EurOBIS databank. Omdat de code nog steeds in java is geprogrammeerd, hangen we nog steeds vast aan een MySQL databank. Dus net zoals bij de GBIF code zouden we een script moeten programmeren om de data in een MSSQL databank te gieten.
Lorenzo Martelé
¬ 15
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Analyse
3.2.2.3 Script maken Hoewel dit waarschijnlijk de snelste en makkelijkste oplossing is, kunnen er in de toekomst heel wat problemen de kop opsteken. De hoofdreden is de verouderde en statische code van de GBIF HIT. Als er ooit wijzigingen moeten gebeuren in de mapping velden-databank, dan ontstaan er heel wat problemen. Zoals ik al eerder vermeld heb, bij wijzigingen van de originele HIT, moeten er eerst heel wat problemen opgelost worden. Verder mogen we ook niet over het hoofd zien dat er geen enkele manier is om automatisch veel DarwinCore Archives te harvesten. Tenslotte is de GBIF HIT heel traag en bevat het veel nutteloze opties die overbodig zijn voor het VLIZ. 3.2.2.4 Bestaand project In het VLIZ was er een bestaand project, dat nog in zijn kinderschoenen staat. Het programma werd gemaakt door een werknemer in het VLIZ, Robin Houthoofdt. Het doel van de applicatie was de originele HIT vervangen. Een goede optie was dus verder werken aan deze code om zo een nieuwe HIT te maken die aan de wensen van het VLIZ voldoet. Deze code was heel basis en bevat vooral een mapping en een simpele GUI. Er is nog geen code om data te harvesten, te transformeren of de data in te geven in de databank. Vermits deze code heel basis is en het VLIZ graag wil overstappen naar het Symfony framework, laat deze code momenteel te wensen over. 3.2.2.5 PHP project (Symfony framework) Het programma zelf terug van nul beginnen maken in het Symfony framework lijkt me de beste mogelijkheid. De code wordt meteen gemaakt volgens de best practices van Symfony. Het programma zal enkel de nodige functionaliteit bevatten en in het totaalpakket zal het programma vlotter en sneller werken dan zijn voorgangers. De laatste twee opties zijn uit de bus gekomen als beste oplossing. De reeds bestaande code gebruiken om een correcte mapping te doen en de HIT beginnen maken in Symfony framework zorgt ervoor dat de best practices meteen worden toegepast.
3.3 Conclusie Om een antwoord te geven op mijn onderzoeksvraag: Waarom worden IPT's en HIT's gebruikt om data te verspreiden tussen onderzoekscentra? Eerst en vooral moet ik de vraag ietwat aanpassen. Een IPT is een programma dat data verwerkt en openstelt voor derden, in de vorm van een DarwinCore Archive. Als er een betere oplossing komt dan een DarwinCore Archive, dan zal de IPT gewijzigd worden om gebruik te maken van de nieuwe oplossing. Het is dus geen IPT, maar DarwinCore Archives die gebruikt wordt om data te verspreiden, een IPT genereert de file alleen maar. Maar de redenering blijft dezelfde. Een DarwinCore Archive wordt gebruikt om data compact, flexibel en leesbaar te verspreiden naar de vragende partijen. Vervolgens wordt een HIT gebruikt om de data te transformeren naar de gewenste structuur. Deze manier om data te verspreiden zal blijven bestaan tot er een beter alternatief komt die het mogelijk maakt om data eenvoudiger te voorzien voor de vragende partijen.
Lorenzo Martelé
¬ 16
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Ontwikkeling
4 Ontwikkeling Mijn stage bestaat uit twee grote onderdelen. Een analyse van HIT mogelijkheden en een ontwikkeling/implementatie van een HIT. Het analyse gedeelte vindt U terug in het vorige gedeelte.
4.1 Fases Ontwikkeling en implementatie is het tweede gedeelte. Voor een duidelijk overzicht te houden ging ik in verschillende fases te werk. 4.1.1 PHP applicatie Mijn ontwikkeling ging van start als een gewone PHP applicatie. Ik wist dat ik moest werken met het Symfony framework, maar voor duidelijkheid en testbaarheid van mijn applicatie, had ik toch gekozen om te beginnen in standaard PHP. Om een goed beeld te scheppen van wat mijn applicatie moet kunnen en waar mijn applicatie gebruikersinput nodig heeft, heb ik van binnen naar buiten toegewerkt. Het binnenste van mijn applicatie is de kern. Hierin wordt alle functionaliteit van mijn applicatie afgehandeld. Om een goed overzicht te houden, heb ik de kern in verschillende klassen gesplitst. Iedere klasse heeft zijn eigen verantwoordelijkheid. -
HarvestOperation: Deze klasse bevat alle methods om de nodige data te downloaden van een extern adres. FileOperation: Deze klasse bevat alle methods die verantwoordelijk zijn om lokaal files aan te maken, te raadplegen en te verwijderen DataOperation: Deze klasse bevat alle methods om de ingelezen data te transformeren zodat deze toepasselijk is voor de EurOBIS databank. GenerateMessage: Deze klasse bevat alle methods voor errorlogging.
Bij het coderen van de kern zijn er niet echt problemen opgedoken. Om de data te harvesten, maak ik gebruik van curl (voor de code: zie Bijlage 1). De file die het meest tijd vergde, was DataOperation. De meeste datatransformaties gingen probleemloos. De enige transformaties die problemen gaven, waren datums, tijden en footprintWKT, maar later meer daarover. 4.1.2 Symfony en GUI Toen de kern af was, moest ik een GUI maken. Ik begon de GUI te maken in het Symfony framework. Ik had gelezen dat Symfony gemakkelijk overweg kon met PHP code, dus dacht ik dat mijn kern zonder problemen ging werken. Helaas was dit niet het geval. Een groot deel van de code kon ik inderdaad kopiëren, maar Symfony werkt met namespaces, klasses, functies, … Dus moest ik mijn PHP code aanpassen naar zo’n formaat. Als ik meer kennis had van Symfony zou ik er niet zoveel tijd aan verloren hebben.
Lorenzo Martelé
¬ 17
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Ontwikkeling
4.1.3 Doctrine Toen mijn programma een simpele GUI had, nam ik mijn databank afhandeling opnieuw onder handen. De originele databankafhandeling was snel, maar netwerkintensief. Symfony heeft een ingebouwde databankafhandeling, namelijk Doctrine. Toen ik gebruik wilde maken van Doctrine kreeg ik een probleem. Mijn applicatie maakt gebruik van een legacy databank. Dit wil zeggen dat mijn databank volgens een oud systeem werkt, waar geen primary keys worden vereist. Doctrine vereist wel een primary key om zijn nodige bewerkingen te kunnen doen. Na enkele pogingen is het dan gelukt om doctrine een primary key te geven, zonder dat deze wordt weggeschreven in de databank. Omdat de databank geen primary key heeft en geen enkele combinatie is 100% zeker uniek, is het niet mogelijk om data te updaten in de databank. Als een DarwinCore Archive wordt bijgewerkt, wordt de originele data verwijderd en opnieuw ingegeven in de databank. 4.1.4 Logging Nu mijn programma alle nodige onderdelen had om te werken, moet er ook een manier zijn om bij te houden als er iets fout gaat. Mijn logsysteem maakt gebruik van de GenerateMessage klasse. De logs worden weggeschreven in 2 bestanden. Enerzijds hebben we een Errorlog, deze bevat fouten die de applicatie oproept. De meeste fouten gebeuren tijdens de datatransformatie. Als een datatransformatie verkeerd gaat, dan wordt er gelogd waar in het bestand de fout gebeurt, wat de data is en wat er werd verwacht. Anderzijds hebben we een Warninglog, deze bevat geen fouten, maar wel vormen van dataverlies. De meest voorkomende waarschuwingen zijn velden die niet naar de databank worden weggeschreven omdat ze niet gemapped zijn in de config file. 4.1.5 Testing De volgende stap was het programma aan een grondige test te onderwerpen. Hier zijn ook nog enkele problemen naar boven gekomen. De eerste fouten die opdoken waren databankproblemen en dan meer bepaald truncated errors. De data die moet worden ingegeven, was te lang voor de databank. Hiervoor waren wijzigingen nodig aan de databank zelf. Het volgende grote probleem waarmee ik moest afrekenen, was te vinden bij de grote bestanden. Mijn programma hield alle data in het geheugen. Bij grote bestanden wordt er teveel geheugen ingenomen. Als oplossing hiervoor heb ik gebruik gemaakt van batches. Iedere 5000 records verwerkt mijn programma deze 5000 en voegt deze toe aan de databank. 4.1.6 Gebruiksvriendelijkheid Nu er een volledig werkende applicatie was, moest er gewerkt worden aan de gebruiksvriendelijkheid. Op dit moment kon de applicatie slechts één opdracht tegelijk verwerken. Initieel kwam ik steeds terecht bij een queueing applicatie (RabbitMQ). In de loop van mijn laatste week heb ik een eigen queueing systeem werkend gekregen. Mijn queue werkt met behulp van een database entry en de kern zit verwerkt in een command. Vervolgens controleert een bat-file of er een entry is in de databank. Als deze er is, dan wordt mijn kern opgestart.
Lorenzo Martelé
¬ 18
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Ontwikkeling
Op vraag van Mr. Vanhoorne heb ik ook nog een progress systeem gemaakt. Als een DarwinCore Archive wordt verwerkt, dan is er een progress update bij iedere 500 records die in de databank worden ingegeven.
4.2 Problemen Tijdens de ontwikkeling van een applicatie steken problemen altijd de kop op. Ook mijn applicatie had te maken met enkele problemen. Tijdens de ontwikkeling van mijn kern doken er enkele problemen op in verband met de datatransformaties. Het hoofdprobleem bij de DarwinCore Archive is het ontbreken van een verplichte standaard voor velden. Ze worden niet verplicht, maar zijn een voorkeur. Bijgevolg moet de HIT deze problemen opvangen. Spijtig genoeg is dit niet altijd mogelijk en wordt er dus aan dataverlies geleden. De grootste problemen bij de datatransformaties zijn datums en tijden omdat er niet altijd rekening werd gehouden met de standaard. Vervolgens hebben we ook nog de FootprintWKT, dit is een gestandaardiseerde manier om coördinaten compact te verzamelen. De WKT moest terug omgevormd worden naar de lengte- en breedtegraad. Deze transformatie moest gebeuren via MSSQL, dus deed ik beroep op doctrine om deze transformatie te doen. Het grootste probleem blijft het formaat. Als de data niet voldeed aan de standaard, die MSSQL nodig heeft, dan ontstaat er een fout die de applicatie doet vastlopen. Dus moet er op voorhand gecontroleerd worden dat de data aan de standaard voldoet. Zoals eerder vermeld, toen ik de overstap maakte van standaard PHP naar het Symfony framework, doken er enkele problemen op met mijn kern. Symfony is een framework in PHP die code verwacht in de vorm van namespaces, klasses, methods, … Dus mijn kern moest herschreven worden om in dit formaat te kunnen werken. Hoewel er niets veranderde aan de functionaliteit van de kern, werd de syntax wel zwaar aangepast. Al deze aanpassingen hebben een goede namiddag aan tijd gekost om mijn kern werkend te krijgen in Symfony. Andere problemen die opdoken, zijn al eerder vermeld en hebben ook al een uitleg gekregen en een oplossing. Deze problemen waren de overstap naar Doctrine, geheugenbeheer (batches) en queueing.
Lorenzo Martelé
¬ 19
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Ontwikkeling
4.3 Codevoorbeelden Voor een beter leesbare versie van de code: zie Bijlagen. 4.3.1 Extracting
(Bijlage 2)
In dit codevoorbeeld wordt er nagegaan welke bestanden er nodig zijn voor de applicatie. Het zip bestand wordt geopend, om vervolgens de nodige bestanden uit te pakken in de juiste locatie. De juiste bestanden worden bepaald in de andere method. Deze informatie wordt bijgehouden in een tabel. Aan deze code is te zien dat er structuurverschillen kunnen zijn afhankelijk van de bron. Bij de extractTo method moet er rekening gehouden worden met de mogelijkheid dat de DarwinCore Archive nog eens in een map zit, zonder naam.
Lorenzo Martelé
¬ 20
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Ontwikkeling
4.3.2 FileHandler
(Bijlage 3)
Dit is een van de langere methods. Hier worden de uitgepakte databestanden ingelezen, per 5000 records, om vervolgens de data te transformeren en in te geven in de databank. Bij deze method ben ik op het probleem van memory managment gestoten. Bij grotere bestanden wordt er teveel data in het geheugen gehouden, als het bestand in één keer moet verwerkt worden. De oplossing was met batches werken.
Lorenzo Martelé
¬ 21
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Ontwikkeling
4.3.3 FootprintWKT
(Bijlage 4)
In deze method moest het veld FootprintWKT worden ingelezen, om vervolgens terug omgezet te worden naar de lengte- en breedtegraden. De omzetting gebeurde door MSSQL. Hierdoor werd het noodzakelijk om enkel geldige data door te sturen. De method validateCoordinates garandeert dat enkel geldige data wordt doorgegeven aan de databank.
Lorenzo Martelé
¬ 22
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Ontwikkeling
4.3.4 Command
(Bijlage 5)
Naar het einde van mijn stage toe, heb ik de kern afgezonderd van de GUI met behulp van een Command. Als een gebruiker een nieuwe dataset wil harvesten (dit kunnen meerdere DarwinCore Archives zijn), dan wordt deze opdracht in een queue gezet. Iedere x minuten, dit wordt bepaald door de taskmanager van de server, wordt een bat-file opgeroepen die deze queue bekijkt. Als er een geldige waarde in de queue zit, dan wordt het command uitgevoerd en dus de kern van de applicatie.
Lorenzo Martelé
¬ 23
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Bespreking van het project
5 Bespreking van het project 5.1 Project Voor mijn project moest ik een HIT programmeren om gemakkelijk DarwinCore Archives te kunnen inlezen en de data te transformeren zodat deze kon toegevoegd worden aan de EurOBIS databank. Omdat het origineel programma verouderd was, wist ik al snel aan welke eisen mijn HIT moest voldoen: -
Mijn programma moet dezelfde functionaliteit hebben Liefst sneller werken dan het origineel Flexibeler zijn naar de toekomst toe, als er wijzigingen ontstaan bij de mapping Iets gebruiksvriendelijker zijn Overweg kunnen met een MSSQL databank OO geprogrammeerd zijn, zodat andere mensen de code sneller begrijpen Meerdere taken kunnen afwerken, liefst onder de vorm van scheduling.
Mijn stage begon met een analyse van de mogelijkheden om een HIT te maken. Vervolgens ben ik begonnen met een kern te maken die alle afhandelingen deed. Tenslotte ben ik dan geëindigd met een GUI voor gebruikersinteractie met de kern. Wegens tijdsgebrek leek ik eerst niet in staat te zijn om meerdere taken te kunnen verwerken. Uiteindelijk ben ik er toch in geslaagd, maar dit kwam wel ten koste van een nieuwe lay-out. Spijtig genoeg heb ik geen volledige schedular kunnen maken en is het een simpel queueing systeem geworden. Maar nu moet de gebruiker niet meer wachten tot de applicatie klaar is met een eerdere opdracht.
Lorenzo Martelé
¬ 24
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Bespreking van het project
5.2 Werking van de applicatie Wanneer de gebruiker de applicatie start, krijgt deze een startvenster (Bijlage 6). In dit venster kan de gebruiker de logs bekijken, de vooruitgang (als er een harvest bezig is) en een nieuwe opdracht geven. Om een nieuwe opdracht te geven, moet de gebruiker een IPTfeed url ingeven.
Nadat de gebruiker een geldige url heeft opgegeven, worden alle geldige datasets weergegeven. Vervolgens kan de gebruiker de datasets selecteren die moeten verwerkt worden. (Bijlage 7). In de volgende stap moet de gebruiker de dataproviders ingeven voor iedere dataset. Als de dataprovider reeds bestaat, dan wordt deze automatisch geselecteerd (Bijlage 8). Als de provider ontbreekt in de databank, dan moet de gebruiker een nieuwe provider aanmaken. (Bijlage 9).
Eenmaal de gebruiker alle dataproviders heeft meegegeven en de opdracht heeft gegeven om de data te verwerken, wordt de opdracht toegevoegd aan een databank. Deze databank wordt gebruikt als een queue waar de kern de opdrachten haalt, met behulp van een bat- file. Tenslotte wordt de gebruiker terug naar de eerste pagina gebracht.
Lorenzo Martelé
¬ 25
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Kritische reflectie
6 Kritische reflectie Ik ben blij dat ik de mogelijkheid heb gekregen om te werken in een echt bedrijf. De manier van werken is volledig anders. Het grootste verschil voor mij was de verplichting om te werken aan een project van 9 tot 17. Als je werkt aan een project voor school kies je al snel je eigen uren of stel je bepaalde taken uit. In een bedrijf is dit absoluut niet het geval. Ik heb ook veel bijgeleerd over mijn eigen manier van werken. Een voorbeeld: Ik ben niet echt een planner en meestal werk ik aan dingen waar ik op het moment zelf aan denk. Maar op mijn stage werd het noodzakelijk om meer structuur in mijn werk te brengen. Door het inbrengen van een structuur in mijn werk, ontstond er een goed overzicht. Ik had een veel beter beeld waaraan ik nog moest werken en wat er nog moest gebeuren aan het project. Na mijn stage besef ik wel dat mijn zelfvertrouwen minder groot is dan ik dacht. Dat wordt duidelijk één van mijn werkpunten. Ik twijfel snel aan iets dat ik heb gemaakt. Om vervolgens veel tijd te verliezen door alles nog eens goed te overdenken en zelfs te wijzigen. En uiteindelijk kom ik vaak terug bij het origineel. Zowel voor, tijdens als na mijn stage merkte ik dat ik geen job zal zoeken met een grote dosis programmeren in de jobomschrijving. Ik kan me weliswaar behelpen en dat heb ik mezelf tijdens de stageperiode ook bewezen. Ik weet dat mijn toekomst bij één van de andere aspecten van informatica ligt. Als ik kijk naar het project zelf was het project zeker interessant voor mij. Ik heb veel bijgeleerd over php en frameworks. Het project heeft me ook aangezet om meer out of the box te denken. In school krijgen we voorgekauwde projecten om aan te werken, terwijl het in de bedrijfswereld totaal anders is. Heel wat bedrijven werken met totaal verschillende structuren. Voor iemand die een programma moet coderen, zijn deze grote verschillen in de structuren het grootste knelpunt. De grootste structuurverschillen zijn tussen bedrijven, maar door de groei en opbouw van een bedrijf komen er vaak ook structuurverschillen voor in het bedrijf zelf. Deze interne structuurverschillen zouden moeten aangepast worden, maar vaak zijn de kosten de moeite niet waard. Mijn project had te maken met een legacy databank. Primary keys worden niet vereist, nu is zo een situatie ondenkbaar. Andere problemen komen naar voor als je data van externe bronnen krijgt. Er moet altijd rekening gehouden worden met een andere structuur, data in een verkeerd formaat, … Deze problemen moeten opgevangen worden door de applicatie. De stage heeft me zeker bijgeleerd dat een diploma slechts het begin is van het leerproces. Als ik mijn stage opnieuw zou moeten doen, dan zou ik wel enkele zaken anders aanpakken. Ik zou meteen beginnen in een framework. Ik had mijn kern gemaakt in standaard php om daarna veel tijd te verliezen bij het overzetten van de kern naar het framework. Ik zou ook zelfzekerder zijn over mijn code en bij problemen sneller om raad vragen.
Lorenzo Martelé
¬ 26
VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT Conclusies
7 Conclusies Na het beslissen van mijn onderzoeksvraag, begon ik na te denken over alternatieve manieren om data te verspreiden. Hoewel ik initieel dacht dat er betere manieren zouden zijn, heb ik mijn mening moeten herzien. Eenmaal je stilstaat bij het feit dat onderzoekscentra niet de enige groepen zijn die deze data opvragen, besef je dat er niet veel alternatieven zijn voor grote dataoverdrachten. Heel wat onderzoekers hebben noch de kennis, noch de programma’s om andere vormen van dataverspreiding te lezen. De grootte van de data is ook heel wat compacter dan ik dacht. Momenteel is het gebruik maken van CSV bestanden voor grote hoeveelheden data nog steeds een goede manier om deze te verspreiden. Heel wat programma’s zijn in staat deze soort bestanden te verwerken. Voor mij was de stage een leerzaam proces. Mijn kennis en persoonlijkheid zijn gegroeid. Scholen bieden je slechts een basis op vlak van kennis. Maar de basis die aangeleerd wordt zorgen er wel voor dat moeilijkere problemen vaak gemakkelijk kunnen opgelost worden. Spijtig genoeg bieden de scholen weinig ondersteuning om eigen kennis uit te breiden. Doorheen de stage heb ik veel zelf moeten leren. De kennis werd vergaard door opzoekingen. Helaas vind ik dat scholen dit niet genoeg ondersteunen. Het zou een student zeker een meerwaarde bieden als ze snel foutieve voorbeelden kunnen onderscheiden van goede. Als eindconclusie vind ik dat de stage en eindwerk een goede meerwaarde bieden aan de opleiding. Door het zelf moeten kiezen van een onderzoeksvraag, wordt er kritischer nagedacht over de stage en wat er wordt gedaan tijdens de stage. Dat is toch mijn mening.
Lorenzo Martelé VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT
8 Bronnen- & literatuurlijst http://www.vliz.be/nl https://code.google.com/p/gbif-indexingtoolkit/source/list http://stackoverflow.com http://www.w3schools.com/ https://symfony.com/ http://php.net/
Lorenzo Martelé VLIZ Oostende
academiejaar 2014-2015 Bouwen van een HIT
9 Overzicht van de bijlagen 1
Curl code
2
Extracting code
3
Reading file code
4
Processing FootprintWKT code
5
Command code
6
Startpagina
7
Dataset pagina
8
Dataprovider pagina
9
Dataprovider toevoegen pagina
Bijlage 1: Curl code /** * Description: Download FileContent from a url * * @param string $url * * @return type */ function collect_file($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_AUTOREFERER, false); curl_setopt($ch, CURLOPT_REFERER, "http://www.xcontest.org"); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_setopt($ch, CURLOPT_HEADER, 0); $result = curl_exec($ch); curl_close($ch);
return ($result); }
Bijlage 2: Extracting code /** * Description: Gets an array with FilesNames. *
Searches for every FileName.zip
*
Creates an extractPath
*
Gets necessary data and stores these in arrays
*
Extracts all necessary files to extractPath
* * @param array $files * * @return multiple arrays */ public function extractFiles() { $files = $this->getFiles(); $dataFiles = $lineSeperators = $fieldSeperators = []; $mofDataFiles = $mofLineSeperators = $mofFieldSeperators = []; foreach ($files as $filename) { $zip = new \ZipArchive(); $res = $zip->open($this->kernelDir . '/data/' . $filename); if ($res === true) { $extractPath = $this->kernelDir . '/extract/' . explode(".", $filename)[0] . '/'; list($dataFile, $lt, $ft) = $this->getDataFile($zip, $extractPath, 'core'); list($mofFile, $mofLt, $mofFt) = $this->getDataFile($zip, $extractPath, 'extension'); $zip->extractTo($extractPath, $dataFile) ? : $zip->extractTo($extractPath, '/' . $dataFile); $zip->extractTo($extractPath, $mofFile) ? : $zip->extractTo($extractPath, '/' . $mofFile); $zip->close(); array_push($dataFiles, $dataFile); array_push($lineSeperators, $lt); array_push($fieldSeperators, $ft);
array_push($mofDataFiles, $mofFile); array_push($mofLineSeperators, $mofLt); array_push($mofFieldSeperators, $mofFt); } } return [$dataFiles, $mofFieldSeperators]; }
$lineSeperators,
$fieldSeperators,
$mofDataFiles,
$mofLineSeperators,
/** * * @param ZipArchive $zip * @param string
$path
* @param string
$tag
* * @return array(datafile, lineterminator, fieldterminator) */ private function getDataFile($zip, $path, $tag) { $zip->extractTo($path, 'meta.xml') ? : $zip->extractTo($path, '/meta.xml'); $reader = new \XMLReader(); $reader->open($path . 'meta.xml'); $dataFile = $lineTerminator = $fieldTerminator = ""; while ($reader->read()) { if ($reader->nodeType == \XMLReader::ELEMENT && $reader->name == $tag) { $xml = new \SimpleXMLElement($reader->readOuterXml()); $attributes = $xml->attributes(); $dataFile = $xml->files->location; $originalChars = ["\\n", "\\t", "\\r", "\\v", "\\f"]; $replaceChars = ["\n", "\t", "\r", "\v", "\f"]; $lineTerminator = str_replace($originalChars, $replaceChars, $attributes->linesTerminatedBy); $fieldTerminator = str_replace($originalChars, $replaceChars, $attributes->fieldsTerminatedBy); } } $reader->close();
return [(string) $dataFile, $lineTerminator, $fieldTerminator]; }
Bijlage 3: Reading file code /** * * @param string $fileName
= path to Filename
* @param string $lineSeparator * @param string $valueSeparator * @param int
$dataprovider = Dataprovider id (only used for DataProcessing)
* @param type
$em
= EntityManager from controller (only used for DataProcessing)
* @param boolean $eurobis
= Check for DataProcessing; either Eurobis or MeasurementOrFacts
*/ function handleFile($fileName, $lineSeparator, $valueSeparator, $dataprovider = null, $em = null, $eurobis = true) { $log = new GenerateMessage($this->kernelDir); $fileArray = $keyArray = []; if (file_exists($fileName)) { try { $batchNr = 0; $log->writeProgress('Processing initiated'); if (($handle = fopen($fileName, "r")) !== false) { $firstline = true; $batch = 0;
while (($data = fgetcsv($handle, 0, $lineSeparator)) !== false) { //read line //Make batches, to save memory with large files if ($batch === 5000) { $log->writeProgress('--- Batch '. $batchNr . ' ---'); //call create inserts $this->processData($keyArray, $fileArray, $dataprovider, $em, $eurobis, $batchNr); $batch = 0; $batchNr++; } else { $batch++; $dataArray = explode($valueSeparator, $data[0]); //divide line in smaller strings foreach ($dataArray as $dataCol => $dataValue) { if ($firstline) { $keyArray[] = $dataValue; $fileArray[$dataCol] = []; } else { if ($batch == 1) { $fileArray[$dataCol] = []; array_push($fileArray[$dataCol], $dataValue); } else { array_push($fileArray[$dataCol], $dataValue);
} } } } $firstline = false; } fclose($handle); } $log->writeProgress('--- Batch '. $batchNr . ' ---'); //call to process batches <5k $missing = $this->processData($keyArray, $fileArray, $dataprovider, $em, $eurobis, $batchNr); foreach ($missing as $mis) { $log->writeWarning('Missing corresponding field to map the data. To edit this, please check the config file. Missing field: ' . $mis); } } catch (\Exception $e) { $log->writeError($e->getMessage()); } } else { $log->writeError($fileName . ' does not exist'); } }
Bijlage 4: Processing FootprintWKT code private function processFootprintWKT($footprintWKT, $axis, $startEnd) { switch ($footprintWKT) { case strcasecmp(explode("(", $footprintWKT)[0], "LINESTRING") == 0: case strcasecmp(explode("(", $footprintWKT)[0], "MULTILINESTRING") == 0: case strcasecmp(explode("(", $footprintWKT)[0], "LINESTRING ") == 0: case strcasecmp(explode("(", $footprintWKT)[0], "MULTILINESTRING ") == 0: $point = $this->repository->executeSQL("geometry::STGeomFromText('" . $footprintWKT . "', 4326)." . $startEnd . ".STAsText()"); break; case strcasecmp(explode("(", $footprintWKT)[0], "MULTIPOINT") == 0: case strcasecmp(explode("(", $footprintWKT)[0], "POLYGON") == 0: case strcasecmp(explode("(", $footprintWKT)[0], "MULTIPOINT ") == 0: case strcasecmp(explode("(", $footprintWKT)[0], "POLYGON ") == 0: if (stripos($footprintWKT, "((") === false) { $search
= ["(", ")"];
$replace
= ["((", "))"];
$footprintWKT = str_replace($search, $replace, $footprintWKT); } $point = $this->repository->executeSQL("geometry::STGeomFromText('" . $footprintWKT . "', 4326)." . $startEnd . ".STAsText()"); break; case strcasecmp(explode("(", $footprintWKT)[0], "POINT") == 0: case strcasecmp(explode("(", $footprintWKT)[0], "POINT ") == 0: //wkt is point $point = $footprintWKT; break; default: $point = null; break; } if (!empty($point) && $this->validateCoordinates($point)) { return $this->repository->executeSQL("geography::STGeomFromText('" . $point . "', 4326)." . $axis); } else { (new GenerateMessage($this->kernelDir))->writeError("Line: " . $this->currentLine . " Invalid coordinates. Expected valid range, got: " . $footprintWKT . " Converted to Point: " . $point);
return null; } }
private function validateCoordinates($point) { $toCheck = explode(" ", rtrim(str_replace("POINT (", "", $point), ")")); if (($toCheck[0] >= -180) && ($toCheck[0] <= 180) && ($toCheck[1] >= -90) && ($toCheck[1] <= 90)) { return true; }
return false; }
Bijlage 5: Command code protected function configure() { $this ->setName('dwcHarvester:nextInQueue') ->setDescription('Get the next record in the dwc_harvester_queue database ' . 'and insert the data into Eurobis database'); } protected function execute(InputInterface $input, OutputInterface $output) { $em = $this->getContainer()->get('doctrine')->getManager(); $queue = $em ->getRepository('DwcHarvesterHitBundle:DwcHarvesterQueue')->getNextInQueue(); if(!empty($queue[0])){ $datafiles = unserialize($queue[0]->getFiles()); $dataproviders = unserialize($queue[0]->getDataproviders()); $this->process($dataproviders, $datafiles); $em >getId());
->getRepository('DwcHarvesterHitBundle:DwcHarvesterQueue')->updateProcessed($queue[0]-
$em->flush(); }else{ $failed = (new GenerateMessage($this->getContainer()->get('kernel')->getRootDir() . '/tmp')); //$failed -> initiate('No Task left'); $failed->writeWarning('Unable to run. Any IPT\'s left? --- ' . date('Y-m-d H:i:s')); } }
Bijlage 6: Startpagina
Bijlage 7: Dataset pagina
Bijlage 8: Dataprovider pagina
Bijlage 9: Dataprovider toevoegen pagina