semantička web-aplikacija zabib.irb.hr/datoteka/891197.final_0036475824_54.pdf · programski okvir...
TRANSCRIPT
SVEUČILIŠTE U ZAGREBU
FAKULTET ELEKTROTEHNIKE I RAČUNARSTVA
DIPLOMSKI RAD br. 1431
Semantička web-aplikacija za
iznajmljivanje smještaja
Marin Božinović
Zagreb, lipanj 2017.
Sadržaj
Uvod ...................................................................................................................................... 1
1. Sematički Web ............................................................................................................... 2
1.1. Formati RDF i RDFS ............................................................................................. 4
1.2. Format OWL i ontologija ...................................................................................... 7
1.3. SPARQL .............................................................................................................. 10
2. Apache Jena Fuseki ..................................................................................................... 13
3. Arhitekturalni stil Redux ............................................................................................. 15
3.1. Stanje ................................................................................................................... 16
3.2. Korisničko sučelje ............................................................................................... 16
3.3. Radnja .................................................................................................................. 16
3.4. Reducer ................................................................................................................ 17
3.5. Spremište ............................................................................................................. 18
4. Radni okvir React.js .................................................................................................... 19
4.1. Container ............................................................................................................. 20
4.2. Component .......................................................................................................... 21
4.3. Arhitekuralni stil Redux s radnim okvirom React.js ........................................... 22
5. Semantička web-aplikacija .......................................................................................... 24
5.1. Funkcionalni zahtjevi .......................................................................................... 24
5.1.1. Opis obrazaca uporabe................................................................................. 24
5.1.2. Sekvencijski dijagrami ................................................................................ 29
5.2. Ontologija aplikacije............................................................................................ 32
5.3. Konfiguracija poslužitelja Fuseki ........................................................................ 34
5.4. Generiranje SPARQL upita ................................................................................. 35
5.5. Korisničko sučelje ............................................................................................... 39
Zaključak ............................................................................................................................. 44
Literatura ............................................................................................................................. 45
Sažetak ................................................................................................................................. 46
Summary .............................................................................................................................. 47
Skraćenice ............................................................................................................................ 48
Privitak A ............................................................................................................................. 49
Privitak B ............................................................................................................................. 50
Privitak C ............................................................................................................................. 63
1
Uvod
Semantička analiza Internet sadržaja otežava pretraživanje web-a i povezivanje
znanja koje web nudi. Semantički web je nadogradnja klasičnog web-a koji uz pomoć
ontologija, odnosno, uz pomoć „znanja o znanju“ olakšava stroju obradu web sadržaja.
Zadatak ovog rada je objasniti semantički web i ontologiju te definirati vlastitu
ontologiju za iznajmljivanje smještaja. Uz to, potrebno je i izraditi samantičku web-
aplikaciju koja omogućava korisnicima filtriranje ponude smještaja uz pomoć semantičkog
rasuđivanja, rezerviranje, ažuriranje i brisanje postojećeg smještaja i stvaranje novih
ponuda. Prilikom razvoja aplikacije potrebno je, za semantičko rasuđivanje, koristiti
programski okvir Apache Jena s poslužiteljem Fusekikomponentom za semantičko
rasuđivanje.
Prvo poglavlje objašnjava ideju i teoriju semantičkog web-a i komponenti koje
omogućuju opisivanje ontologije. U drugom poglavlju je ukratko opisan Fuseki,
komponenta radnog okvira Apache Jena. Treće poglavlje opisuje arhitekturalni stil Redux
koji se koristio prilikom razvoja aplikacije. Tema četvrtog poglavlja je opis radnog okvira
React.js koji se koristio prilikom izrade korisničkog sučelja aplikacije. Peto poglavlje
opisuje procesni tok aplikacije i prikazuje krajnje rješenje rada.
2
1. Sematički Web
World Wide Web je sustav međusobno povezanih hipertekst dokumenata kojem se
pristupa putem Interneta. Tim Berners-Lee je razvio WWW 1989. godine, a 1991. godine
je pušten u javnost. Glavna ideja WWW-a je bilo povezivanje hipertekst dokumenata s
jedinstvenim URL (engl. Uniform Resource Locators) adresama kako bi se korisnicima
omogućio jednostavan pristup tim dokumentima.
Brz tehnološki razvoj je doveo do sve veće potrebe komunikacije između strojeva, a
ne ljudi, za što je WWW bio predviđen. Tim Barners-Lee je definirao semantički web.
Semantički web je nadogradnja klasičnom WWW-u koji sadržaj Internet-a definira
pomoću XML (engl. Extensible Markup Language) dokumenata[1]. XML svojom
strukturom elemenata i atributa omogućava jednostavno opisivanje i povezivanje sadržaja
Interneta, što pojednostavljuje strojnu obradu tih informacija. Osnovne prednosti
semantičkog web-a nad WWW-om su mogućnost višekratnog korištenja informacija u
različitim aplikacijama i bolja strojna obrada semantike informacija što povećava točnost
web tražilica (engl. search engine).
Slika 1.1 prikazuje stog semantičkog web-a[2] koji sadrži:
• URI (engl. Uniform Resource Identifier) – jedinstveni niz znakova koji se koristi za
identificiranje sadržaja
• Unicode – standard za kodiranje, obradu i prikazivanje teksta
• XML – skup pravila za strukturiranje dokumenata u formatu razumljivom i ljudima
i strojevima
• RDF (engl. Resource Description Framework) – metoda konceptualnog opisivanja
i modeliranja informacija u trojke
• RDFS (engl. Resource Description Framework Schema) – opisni jezik za
definiranje rječnika pojmova
• RIF (engl. Rule Interchange Format) – skup pravila za prijelaze iz jednog formata
pravila u drugi
3
• OWL (engl. Web Ontology Language) – skup pravila za opisivanje znanja
ontologije
• SPARQL (engl. SPARQL Protocol and RDF Query Language) – upitni jezik za
dohvaćanje i obradu informacija pohranjenih u RDF formatu.
U nastavku poglavlja definirane su ontologije te su opisani glavni dijelovi stoga
semantičkog weba i primjenjivanje semantičkog reasoner-a.
Slika 1.1 Stog semantičkog web-a
4
1.1. Formati RDF i RDFS
RDF je temeljni format za opisivanje i obradu metapodataka. Aplikacijama koje
izmjenjuju informacije pruža interoperabilnost potrebnu za strojnu obradu. RDF se bazira
na objektima koji omogućuju automatiziranu obradu web sadržaja. Automatizirana obrada
može imati različite primjene kao što su poboljšanje rezultata search engine-a,
kategorizacija sadržaja i opis povezanosti sadržaja. Glavni cilj RDF-a je definiranje
mehanizama za opisivanje sadržaja bez stvaranja pretpostavki o domeni ili semantici
aplikacija koje koriste taj sadržaj[3]. Iako mehanizmi trebaju biti neovisni o domeni,
moraju je moći opisati.
Osnove RDF-a su principi preuzeti iz različitih modela za opisivanje podataka.
RDF svojstva i vrijednosti pridružene tim svojstvima mogu se jednostavno shvatiti kao
ključ-vrijednost par i zbog toga sliče entitet-relacijskom modelu relacijskih baza podataka,
odnosno atributima objekata objektno-orijentiranih programskih jezika.
Osnovni model se sastoji od tri tipa objekata:
1. sadržaj
2. svojstvo
3. izjava.
Sadržaj predstavlja sve što se opisuje RDF-om. Sadržaj može biti cijelo web sjedište,
samo jedna web stranica ili dio web stranice. Sadržaj može biti i objekt koji nije direktno
dostupan putem Interneta. Sadržaj je uvijek definiran URI-em i opcionalno dodatnim
identifikatorom.
Svojstvo je aspekt, karakteristika, atribut ili relacija koja se koriti za opisivanje
sadržaja. Svako svojstvo ima specifično značenje koje definira dozvoljene vrijednosti i tip
sadržaja koji je opisan odnosima s drugim svojstvima.
Sadržaj s pridruženim svojstvom i vrijednošću pridruženu tom svojstvu tvori RDF
izjavu. Sadržaj predstavlja subjekt, svojstvo predikat, a vrijednost svojstva objekt izjave.
Objekt izjave može biti ili drugi sadržaj definiran vlastitim URI-em ili literal.
Prilikom stvaranja RDF izjava, svaka izjava se kreira po modelu <subjekt> ima
<predikat> <objekt>. U modelu, <subjekt> označava sadržaj, odnosno resurs
5
koji opisuje RDF i pridružen mu je URI. Svojstvo pridruženo sadržaju je <predikat>, a
<objekt> je vrijednost svojstva.
Slika 1.2 prikazuje vizualizaciju trojke za primjer „Ora Lassila is the creator of the
resource http://www.w3.org/Home/Lassila“ [3]. Primjer rečenice može se podijeliti na
subjekt http://www.w3.org/Home/Lassila, predikat Creator i objekt Ora Lassila.
Slika 1.2 Vizualizacija RDF trojke
Kôd 1.1 prikazuje RDF reprezentaciju prikazanog primjera.
<rdf:RDF>
<rdf:Description about="http://www.w3.org/Home/Lassila">
<s:Creator>
Ora Lassila
</s:Creator>
</rdf:Description>
</rdf:RDF>
Prilikom vizualizacije RDF izjava, subjekt se prikazuje kružnicom, predikat
strelicom, a objekt, ovisno o tipu, kružnicom ili pravokutnikom. Ako se objekt definira
drugim resursom, odnosno, ako je definiran URI-em, prikazuje ga se kružnicom, ako je
definiran literalomm, prikazuje ga se pravokutnikom. Smjer strelice je važan i uvijek ide
od subjekta prema objektu izjave.
Jedan od problema RDF-a je što ne nudi mehanizme za deklariranje svojstava ni
mehanizme za definiranje odnosa između svojstava i drugih sadržaja. Kako bi se riješio taj
problem, definira se RDFS kao nadogradnja RDF-u.
RDFS je definiran kao RDF sadržaj koji se može koristiti za opisivanje svojstava
drugih RDF sadržaja koji opisuju vokabulare specifične za pojedine aplikacije. Kako bi se
osiguralo konzistentno korištenje svojstava i klasa, RDFS uvodi niz RDF sadržaja za
stvaranje izjava o ograničavanju RDF podataka.
Kôd 1.1 RDF primjer
6
U nastavku su navedena i ukratko opisana svojstva koja RDFS uvodi.
Za modeliranje klasa, RDFS uvodi:
• rdfs:Class – odgovara konceptu klase objektno-orijentiranih programskih jezika
• rdfs:subClassOf – tranzitivno svojstvo za definiranje podklasa i nadklasa.
RDFS dozvoljava višestruko nasljeđivanje, odnosno dozvoljava da jedna klasa bude
podklasa više različitih klasa.
Kako bi se postiglo ograničavanje vrijednosti svojstava, RDFS uvodi:
• rdfs:domain – specificiranje klase u kojoj se svojstvo može koristiti
• rdfs:range – koristi se za ograničavanje vrijednosti svojstva, odnosno definiranje
klase koja se može koristi prilikom postavljanja vrijednosti nekom svojstvu
• rdfs:subPropertyOf – specificiranje da je jedno svojstvo specijalizacija drugog
svojstva.
Definiraju se specijalne klase i predikati:
• rdfs:Resource – sve što je definirano RDF-om, ekvivalentno objektu objektno-
orijentiranih programskih jezika
• rdfs:Literal – atomarne vrijednosti kao što su cijeli broj, decimalni broj i tekst,
• rdfs:comment – opis sadržaja prirodnim jezikom
• rdfs:seeAlso – definira sadržaj koji opisuje informacije o subjektu neke izjave
• rdfs:isDefinedBy – podsvojstvo svojstva rdfs:seeAlso koje omogućava da resurs
definira subjekt izjave
• rdfs:label – URI prikazan u prirodnom jeziku.
Slika 1.3 prikazuje jednostavan odnos između RDF-a i RDFS-a.
7
Slika 1.3 Mapiranje RDFS-a u RDF
Definiranje RDF-a i RDFS-a osigurava sintaksnu točnost sadržaja web-a, ali ne i
semantičku, što je i cilj semantičkog web-a. Kako bi se osigurala i semantika sadržaja
definira se OWL koji je prikazan u nastavku rada.
1.2. Format OWL i ontologija
Ontologija je eksplicitna, formalna specifikacija zajedničke konceptualizacije [4].
Konceptualizacija označava da ontologija opisuje apstraktni model sadržaja, odnosno
domenu, koncepte i odnose među konceptima. Eksplicitnost znači da model nije
dvosmislen i da svi koncepti moraju biti definirani. Ontologija je formalna, odnosno
razumljiva je računalima i zajednička, odnosno poznatog i općepriznatog značenja.
Svaka ontologija se sastoji od terminološkog (TBox) i asertivnog (ABox) znanja.
TBox opisuje apstraktne koncepte i veze među njima, dok ABox opisuje konkretne
instance i njihove veze s drugim instancama i konceptima iz terminološkog znanja. ABox
izriče činjeničnost, a ne nužnost ili mogućnost. Ne može postojati jedna globalna
ontologija jer je ontologija dinamična i svaka osoba može imati vlastitu perspektivu ovisno
o domeni interesa.
Ontologija se opisuje uz pomoć:
• klasa – skup entiteta koji dijele jednaka svojstva i ponašanja opisani atributima
8
• instance – konkretni entiteti koji pripadaju jednoj ili više klasa
• veze – specijalni atributi koji povezuju klase čije su vrijednosti objekti drugih klasa
• ograničenja – pravila koja definiraju dozvoljene vrijednosti veza i atributa.
Na slici 1.4 je prikazan primjer odnosa TBox-a i ABox-a.
Slika 1.4 Međuodnos TBox-a i ABox-a
Instanciranje web ontologije se ostvaruje opisnim jezikom OWL. Glavna prednost
formata OWL je mogućnost korištenja alata za semantičko rasuđivanje koji neovisno o
domeni opisanoj OWL-om mogu analizirati formalnu semantiku za izvođenje logičkih
posljedica i činjenica koje nisu eksplicitno definirane ontologijom.
Jezik OWL nudi tri izražajna podjezika za specifične primjene:
1. OWL Lite – podržava klasifikaciju objekata i jednostavno, binarno ograničavanje
vrijednosti
2. OWL DL (engl. Description Logic) – pruža učinkovito rasuđivanje u konačnom
vremenu, uključuje sve OWL konstruktore s ograničenjem da klasa ne može biti
svojstvo
9
3. OWL Full – pruža maksimalnu izražajnost i sintaksnu slobodu što dovodi do
mogućnosti definiranja neodredivih dokumenata.
Cilj OWL-a je stvoriti web sadržaj koji je više dostupan automatiziranom procesu
dodavanjem informacija o sadržaju koji opisuje ili nudi taj web sadržaj. Svaka OWL
ontologija mora biti otvorena. Otvorenost ontologije znači da se klase jedne ontologije
mogu koristiti u drugim ontologijama. Posljedica toga je da nove informacije ne mogu
poništiti već postojeće informacije. Nove informacije mogu biti kontradiktorne, ali
činjenice se ne mogu brisati, što osigurava semantičku točnost ontologije.
Svaka OWL izjava se sastoji od klase, jedinke i predikata koji odgovaraju klasi,
instanci klase i predikatu izjave RDFS-a. OWL predefinira dvije klase:
• owl:Thing – nadklasa svih klasa koja sadrži sve instance opisane ontologijom
• owl:Nothing – prazan skup disjunktan s bilo kojim nepraznim skupom.
Najvažniji konstruktori OWL-a su:
• intersectionOf – opisivanje klase presjekom dviju ili više drugih klasa
• unionOf – opisivanje klase unijom dviju ili više drugih klasa
• complementOf – definiranje svojstva koje govori da instance jedne klase ne
pripadaju određenoj klasi
• oneOf – definiranje klase s unaprijed određenim vrijednostima koje može primiti
• hasValue – omogućava specificiranje klase ovisno o postojanju određenog svojstva
• minCardinality – definiranje donje granice vrijednosti koje neko svojstvo može
imati
• maxCardinality - definiranje gornje granice vrijednosti koje neko svojstvo može
imati
• cardinality – definiranje točnog broja elemenata u relaciji, npr. klasa Osoba može
imati točno jedno svojstvo datumRođenja.
Aksiomi koje uvodi OWL su:
• subClassOf – specijalizacija klasa
• equivalentClass – indikacija da dvije klase imaju iste instance
10
• subPropertyOf – specijalizacija svojstva
• equivalentProperty - indikacija da dva svojstva imaju iste vrijednosti
• disjointWith – osigurava da instanca jedna klase sigurno neće biti i instanca druge
• sameAs – indikacija da su dvije klase ili svojstva jednaki
• differentFrom – indikacija da su dvije klase ili svojstva različiti
• inverseOf – definira da su dva inverzna svojstva dviju klasi povezani, npr. klasa
Auto ima svojstvo proizvođač, a klasa AutoProizvođač ima svojstvo
proizvedeniAuto
• TransitiveProperty – definira tranzitivnost svojstava
• FunctionalProperty – definira jednakost svojstava.
Opisivanjem jezika OWL objašnjena su svojstva ontologije, odnosno svojstva
informacija koja se koriste za semantički web. U nastavku rada je opisan upitni jezik
SPARQL koji se koristi za pretraživanje izjava ontologije.
1.3. SPARQL
Komponenta semantičkog web-a zadužena za postavljanje semantičkih upita je
jezik i protokol SPARQL. SPARQL se kao protokol temelji na HTTP-u (engl. HyperText
Transfer Protocol) i zadužen je za prijenos upita i odgovora između klijenta i baze znanja.
Kao jezik se temelji na uzorcima trojki subjekt-predikat-objekt, a sintaksa mu se temelji na
SQL-u (engl. Structured Query Language) [4].
SPARQL može dohvaćati podatke u obliku URI-a, literala i praznih čvorova,
odnosno definiranjem trojki i traženjem u ontologiji onih izjava koje zadovoljavaju tu
trojku ili korištenjem agregacija, grupiranja, projekcija i negacija. Osim pretraživanja
ontologija, SPARQL može kreirati nove grafove, prevoditi RDF podatke iz jednog
vokabulara u drugi i povezivati podatke iz heterogenih izvora.
Sintaksa SPARQL-a za definiranje URI-a koristi „< “ i „ > “ znakove i omogućava
definiranje skraćenica za svaki pojedini URI kako je prikazano u primjeru:
PREFIX skarcenica: <http://domena.domena/URI#primjer>
11
Varijable se definiraju s ?imeVarijable i međusobno se odvajaju zarezom. Ovisno
o tipu literala, možemo ih definirati na sljedeće načine:
1. “plain literal“ – definicija običnog literala
2. “obicni literal“@hr – definicija literala s oznakom prirodnog jezika
3. “24“^^xsd:integer – definicija literala s tipom podataka.
Kôd 1.2 opisuje osnovnu strukturu SPARQL upita.
PREFIX a:<http://some.uri/a>
PREFIX b:<http://some.uri/b>
...
SELECT ?var1, ?var2, ...
FROM <http://some.uri/c>
FROM NAMED <http://some.uri/d>
WHERE {
...
}
GROUP BY ...
HAVING ...
ORDER BY ...
LIMIT ...
OFFSET ...
VALUES ...
Svaki SPARQL upit započinje definiranjem skraćenica URI-a korištenih u upitu.
Nakon toga slijedi ključna riječ SELECT i navođenje varijabli koje definiraju rezultat
upita. FROM i FROM NAMED su opcionalne ključne riječi koje se koriste za definiranje
skupa podataka nad kojim se izvodi upit. WHERE je dio upita u kojem se definira traženi
uzorak. Traženi uzorak se opisuje trojkama ekvivalentnim izjavama formata RDF.
Kombiniranje trojki u WHERE dijelu upita se može ostvariti na više načina prikazanih u
nastavku gdje A i B predstavljaju povezane trojke:
• A . B – povezuje rezultate uzorka A s rezultatima uzorka B preko jednakih
vrijednost zajedničkih varijabli
Kôd 1.2 Osnovna struktura SPARQL upita
12
• A OPTIONAL { B } – povezuje rezultate uzorka A s rezultatom uzorka B preko
jednakih vrijednost zajedničkih varijabli, a u slučaju nemogućnosti povezivanja
rezultata zadržava rezultate uzorka A
• { A } UNION { B } – uključuje rezultate oba uzorka
• A MINUS { B } – prikazuje samo one rezultate uzorka A koji se ne pojavljuju
kao rezultat uzorka B
• A . { SELECT ... WHERE { B } } – uzorak B se rješava kao podupit i
njegovo rješenje se povezuje s rješenjem uzorka A
• A . FILTER ( izraz ) – isključuje one rezultate uzorka A koji ne
zadovoljavaju izraz FILTER dijela.
Izraz filtera se definira sljedećim operatorima:
• !A – negacija xsd:boolean vrijednosti
• isURI(A) – provjeravanje je li vrijednost A definirana URI-em
• isLiteral(A) – provjeravanje je li vrijednost A definirana literalom
• STR(A) – pretvaranje URI vrijednost u niz znakova
• &&, || – logički operatori I i ILI
• =, != – operatori usporedbe
• <, >, <=, >= – operatori usporedbe za brojčane podatke
• +, -, *, / – aritmetički operatori za brojčane podatke
• REGEX(niz, uzorak) – pretraživanje regularnih izraza.
Kako bi se mogle čitati i pisati RDF trojke, odnosno kako bi se mogao izvesti SPARQL
upit nad podatcima potreban je poslužitelj koji nudi sementički reasoner. Iz tog razloga je
u sljedećem poglavlju opisan poslužitelj Fuseki.
13
2. Apache Jena Fuseki
Apache Software Foundation je neprofitabilna organizacija koja se bavi razvojem
softverskih proizvoda. Organizacija je decentralizirano društvo programera otvorenog koda
koje svoje proizvode nude besplatno pod uvjetima Apache licence. Projekte vode
samoizabrani timovi volontera. Jedan od projekata razvijen pod Apache organizacijom je i
Apache Jena, radni okvir za rad sa semantičkim web-om.
Apache Jena nudi programsko sučelje (API - engl. Application Programming
Interface) za čitanje i pisanje RDF trojki, Java procesor za SPARQL ARQ i različite
sustave za pohranu trojki i izvođenje upita nad njima. Jedno od sučelja koje nudi je i
poslužitelj Fuseki.
Poslužitelj Fuseki je HTTP konfigurabilno sučelje RDF podataka koji podržava
SPARQL upite. Poslužitelj se konfigurira definiranjem usluga koje nudi i opisivanjem
skupova podataka (engl. dataset) koje pridružuje tim uslugama. Poslužitelj nudi i vlastito
web sučelje za izvođenje SPARQL upita.
Definiranje usluge prikazano je kôdom 2.1. Dva bitna dijela definicije su
fuseki:name i fuseki:dataset. Dok fuseki:name definira ime usluge, pa
samim time i pristupnu točku usluge, fuseki:dataset definira dataset pridružen
usluzi.
<#service1> rdf:type fuseki:Service ;
fuseki:name "ds" ;
fuseki:serviceQuery "query" ;
fuseki:serviceQuery "sparql" ;
fuseki:serviceUpdate "update" ;
fuseki:serviceUpload "upload" ;
fuseki:serviceReadWriteGraphStore "data" ;
fuseki:serviceReadGraphStore "get" ;
fuseki:dataset <#dataset-mem> ;
.
Kôd 2.1 Definicija usluge poslužitelja Fuseki
14
Ostali dijelovi defincije označavaju akcije nad dataset-om koje usluga dozvoljava.
Fuseki ni na koji način ne nudi sigurnost ili kontrolu pristupa. Sigurnost se mora
postići kontroliranjem mreže stroja na kojoj je poslužitelj pokrenut. Preporučuje se
autentifikacija i ograničavanje broja veza koje poslužitelj otvara, blokiranje porta na kojem
Fuseki prati promet za sve vanjske pakete ili pokretanje Fuseki poslužitelja na lokalnom
mrežnom sučelju stroja.
Vođenje dnevnika promjena se vodi preko Log4J alata koji je također razvila Apache
organizacija. Log4J nudi višenitno, asinkrono vođenje dnevnika različitih razina.
Omogućava korištenje predefiniranih razina dnevnika, npr. ERROR, INFO i DEBUG, i
definiranja vlastitih razina. Fuseki poslužitelj definira svoje dvije razine SERVER i
FUSEKI. Razina SERVER prati opće poruke poslužitelja, a razina FUSEKI prati sve
zahtjeve koje poslužitelj prima.
15
3. Arhitekturalni stil Redux
Arhitekturalni stil Redux je jedno on najpopularniji rješenja [6] razvoja kompleksnih
jednostraničnih web-aplikacija (engl. single-page application). Temelji se na arhitekturi
Flux prikazanoj na slici 3.1, koju je razvio Facebook radi smanjenja spaghetti koda svojih
aplikacija.
Slika 3.1 Arhitektura Flux
Razvojem web tehnologija, podatci koji se moraju pamtiti na pregledniku su veći i
složeniji. Odgovori poslužitelja, pričuvni podatci preglednika, podatci koji još nisu
perzistirani na poslužitelju te informacije o različitim komponentama korisničkog sučelja
moraju se sigurno i brzo ažurirati i čuvati[7]. Kako bi to ostvario, Redux pokušava
mijenjanje stanja učiniti predvidljivim uvođenjem ograničenja koja se temelje na tri
principa:
• jedan izvor istine
• stanje se može samo čitati (engl. read-only)
• stanje se mijenja samo „čistim“ radnjama.
Na slici 3.2 je prikazana arhitektura Redux, a u nastavku poglavlja objašnjeni su
pojedini dijelovi arhitekture i njihove uloge u ostvarivanju navedenih principa.
16
Slika 3.2 Arhitektura Redux
3.1. Stanje
Stanje predstavlja jedan izvor istine koji u jednom JavaScript Object Notation
objektu sadrži opis dijela aplikacije. Radi pojednostavljanja razvoja single-page aplikacija
i preglednosti kôda, Redux omogućava definiranje više komponenti Stanje. Za svaku
komponentu Stanje mora se definirati posebna komponenta Reducer. Prilikom
kompiliranja sve Stanje i Reducer komponente se povezuju u jednu kako bi se osigurao
jedan izvor svih informacija i jedna komponenta zadužena za ažuriranje stanja.
3.2. Korisničko sučelje
Kako bi se ostvario princip da je Stanje read-only, Korisničko sučelje je zaduženo
samo za prikaz informacija definiranih u komponenti Stanje. Sve akcije koje korisnik
napravi na sučelju se preusmjeruju prema komponenti Radnja.
3.3. Radnja
Komponenta Radnja je zadužena za preusmjeravanje svih korisničkih akcija
komponenti Reducer. Preusmjeravanje se izvršava naredbom
dispatch(pureActioin). Dispatch je zadana funkcija komponente Skladište, a
17
pureAction je akcija koju definirana programer koja na „čist“ način omogućava
mijenjanje stanja. Sve pureAction funkcije su definirane tipom akcije. Komponenta
Radnja definicije akcija koristi prilikom opisivanja korisničke akcije kako bi komponenta
Reducer znala na koji način oblikovati novo stanje. Sve pureAction funkcije vraćaju
objekt koji prolazi kroz komponentu Reducer u kojem se definira novo stanje.
function pureInputAction (userInput) {
return {
type: actionType1,
value: userInput
}
}
3.4. Reducer
Komponenta Reducer je zadužena za ostvarivanje „čistog“ mijenjanja stanja. U
kôdu je opisana jednom funkcijom koja prima dva argumenta - state i action. State
predstavlja trenutno stanje koje se nalazi u komponenti Spremište, a action je objekt koji
stvara komponenta Radnja. Funkcija komponente Reducer se sastoji od jednog switch-case
bloka koji, ovisno o tipu „čiste“ radnje, na poseban način opisuje novo stanje koje se šalje
komponenti Spremište.
function reducer(state = initialState, action) {
switch(actioin.type) {
case actionType1:
return Object.assign({}, state, {inputValue:
action.value});
default:
return state;
}
}
Funkcija kod definicije argumenata, argumentu state pridružuje inicijalno stanje
initialState kako bi se prilikom pokretanja aplikacije uspješno postavilo inicijalno
stanje aplikacije. Svaki case blok na kraju stvara novi objekt koji se kreira kombiniranjem
Kôd 3.1 Primjer pureAction-a
Kôd 3.2 Primjer reducer-a
18
trenutnog stanja i vrijednostima definiranim action argumentom. Novi objekt se šalje
komponenti Spremište kao stanje u koje aplikacija treba prijeći.
3.5. Spremište
Spremište je glavna komponenta arhitekture Redux. Uloga Spremišta je povezivanje
ostalih komponenti. Brine se da korisničko sučelje funkcijom getState() može čitati
stanje aplikacije, dok komponenta Radnja može pozivati funkciju dispatch(action)
kako bi se stanje promijenilo. Aplikacija može imati samo jedno Spremište koje povezuje
sve komponente Stanje i Reducer koje programer definira. Prilikom pokretanja aplikacije,
poziva se funkcija createStore(reducer, state) koja stvara objekt sa svim
reducer-ima i stanjima.
Arhitekturalni stil Redux se u praksi kombinira sa ranim okvirom React.js koji je
opisan u sljedećem poglavlju.
19
4. Radni okvir React.js
Radni okvir React.js je JavaScript knjižnica za razvoj korisničkih sučelja. Glavna
primjena radnog okvira je jednostavan razvoj komponente Korisničko sučelje arhitekture
Redux. Prilikom razvoja aplikacije korisničko sučelje se dijeli na manje dijelove. Dijelovi
sučelja, ovisno o složenosti i svrsi, definiraju se kao Container ili Comoponent [8] koje su
detaljnije opisani u nastavku poglavlja. Ract.js omogućava da se prilikom mijenjanja stanja
ne osvježava cijela aplikacija nego samo dijelovi na koje promjena utječe. Time se postiže
brzo i reaktivno osvježavanje korisničkog sučelja.
Iako JavaScript nije objektno-orijentirani jezik, prilikom razvoja aplikacija
korištenjem radnog okvira React.js, programer definira klase koje se prilikom kompiliranja
prevode u JavaScript funkcije i objekte. Svaki dio sučelja nasljeđuje klasu Component
definiranu radnim okvirom React.js. Klasa Component sadrži atribute props i state.
Props je objekt koji predstavlja vanjsko, a state unutarnje stanje komponente. Svaka
komponenta je definirana funkcijama i ima životni ciklus prikazan na slici 4.1.
Slika 4.1 Životni ciklus Ract.js komponente
20
Sve funkcije osim getInitialProps() i getInitialState() se mogu
nadjačati, a funkcija setState() omogućava mijenjanje unutarnjeg stanja komponente
do kojeg se najčešće dolazi korisničkim akcijama. Funkcije koje se nadjačavaju omogućuju
programeru bolju kontrolu nad tokom informacija, vanjskim i unutarnjim stanjem
komponente i osvježavanje prikaznih podataka. Nadjačavanje je opcionalno za sve
funkcije osim funkcije render() koja se mora definirati. Povratna vrijednost funkcije
render definira što komponenta prikazuje, odnosno, render funkcija vraća JSX
elemente koji se prilikom kompiliranja prevodi u JavaScript kôd za dinamičko stvaranje
HTML (engl. HyperText Markup Language) elemenata. Kôd 4.1 prikazuje primjer izlaza
funkcije render, dok kôd 4.2 prikazuje rezultat kompiliranja.
<div>
<input type=“text“ />
</div>
React.createElement(
"div",
null,
React.createElement("input", { type: "text" })
);
U nastavku dan je opis Component i Conatiner komponenti radnog okvira React.js
i način njihovog povezivanja s arhitekuralnim stilom Redux.
4.1. Container
Container komponenta je zadužena za definiranje kako aplikacija radi. Sva logika
aplikacije i kontrola stanja se odvija unutar container-a nadjačavanjem navedenih funkcija
React komponente i definiranjem vlastitih funkcija za upravljanje unutarnjeg stanja.
Funkcija render može stvarati component komponente i druge container-e. U
kombiniciji s arhitekturom Redux, container je zadužen za dohvaćanje Redux stanja i
pozivanje funkcije Redux komponente Radnja.
Kôd 4.1 Primjer JSX elementa
Kôd 4.2 Rezultat kompiliranja primjera
21
4.2. Component
Component je dio React.js-a zadužen za izgled aplikacije. Iako može sadržavati
vlastito unutarnje stanje, u pravilu koristi samo vanjsko stanje koje prima od container-a.
Unutarnje stanje se ne definira kako bi se jedan component mogao višekratno koristiti. Kôd
4.3 prikazuje odnos container-a i component-a.
class Conatainer extends React.Component {
constructor(props) {
super(props);
this.state = {userInput: ''};
this.onUserInputChange =
this.onUserInputChange.bind(this);
}
onUserInputChange(event) {
this.setState({userInput: event.target.value});
}
render() {
return (
<MyInput
value={this.state.userInput}
onInput={this.onUserInputChange}
/>
)
}
}
class MyTextInput extends React.Component {
render() {
return (
<input type=“text“
value={this.props.value}
onChange={this.props.onInput}
/>
)
}
}
Kôd 4.3 Odnos React.js container-a i component-a
22
Klasa MyTextInput je component koja kao vanjsko stanje prima value kao
vrijednost koju prikazuje i onInputChange kao funkciju koju poziva prilikom unosa
teksta u input tag. Klasa Container zadužena je za čuvanje i mijenjanje stanja koje
MyTextInput prikazuje.
4.3. Arhitekuralni stil Redux s radnim okvirom React.js
Kada React.js koristimo u sklopu Redux arhitekture, component se ne mora
prilagođavati. Container se prilagođava tako da ga povezujemo s komponentama Stanje i
Radnja arhitekture Redux. Povezivanje se postiže uz pomoć funkcija connect i
bindActionCreators knjižnice React-Redux. Funkcija connect kao argumente
prima Redux stanje i akcije koje šalje container-u kao vanjsko stanje, a funkcija
bindActionCreators osigurava da se sve „čiste“ akcije pozivaju funkcijom
dispatch. Kôd 4.4 prikazuje klasu Container iz prethodnog primjera izmijenjenu u
svrhu povezivanja s Redux stanjem.
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {userInput: props.reduxState.inputValue};
this.onUserInputChange =
this.onUserInputChange.bind(this);
}
componentWillReceiveProps(nextProps) {
this.setState({
userInput: nextProps.reduxState.inputlue
})
}
onUserInputChange(event) {
this.props.action.puerInputAction(event.target.value);
}
render() {
return (
<MyInput
value={this.state.userInput}
onInput={this.onUserInputChange}
/>
)
23
}
}
mapStateToProps = (state) => {
return {reduxState: state}
}
mapDispatchToProps = (dispatch) => {
pureInputAction: bindActionCreators(pureActions);
}
connect(mapStateToProps, mapDispathcToProps)(Container);
Nakon objašnjenja teorije semantičkog web-a i korištenih tehnologija, u radu slijedi
opis ontologije, konfiguracije poslužitelja Fuseki i implementacije aplikacije na primjeru
web-aplikacije rezervacije smještaja.
Kôd 4.4 Primjer povezivanja Redux arhitekture i React.js radnog okvira
24
5. Semantička web-aplikacija
Aplikacija za iznajmljivanje smještaja je razvijena kao Node.js web-aplikacija koja
ovisno o korisničkim akcijama generira SPARQL upite i šalje ih poslužitelju Fuseki koji
omogućava pretraživanje definirane ontologije. Komunikacija poslužitelja i aplikacije je
definirana tako da se obje komponente pokreću na istom stroju. U nastavku su detaljno
prikazani funkcionalni zahtjevi aplikacije, definicija ontologije, konfiguracija poslužitelja
Fuseki, generiranja SPARQL upita i upute korištenja aplikacije.
5.1. Funkcionalni zahtjevi
Namjena aplikacije je olakšati korisnicima pretraživanje i rezervaciju smještaja.
Trenutna rješenja, iako imaju veliku ponudu smještaja, imaju limitirane filtere za
pretraživanje ponuda. Glavna funkcionalnost aplikacije je filter koji uz pomoć semantičkog
rasuđivanja pretražuje ontologiju smještaja i osigurava prikaz onih ponuda smještaja koji
zaista odgovara korisnikovim željama. Kako bi se pokazala ispravnost i prednost
semantičkog rasuđivanja, aplikacija nudi i filtriranje ponuda bez korištenja semantičkog
rasuđivanja. Uz filtriranje, aplikacija nudi mogućnost dodavanja novih sadržaja, kao i
njihovo uređivanje i brisanje.
Funkcionalni zahtjevi i opis toka aplikacije su detaljnije prikazani kroz obrasce
uporabe i sekvencijske dijagrame koji su opisani u nastavku poglavlja.
5.1.1. Opis obrazaca uporabe
UC1 – Filtriraj smještaj
• Glavni sudionik: korisnik
• Cilj: Filtrirati izbor ponuđenih smještaja
• Sudionici: Sustav, Fuseki
• Preduvjet: Korisnik ima pristup Internet-u
• Rezultat: Izbor smještaja je filtriran
25
• Željeni scenarij:
1. Korisnik postavlja željene filtere
2. Sustav generira upit i šalje ga poslužitelju Fuseki
3. Fuseki obrađuje upit i vraća rezultat
4. Sustav parsira rezultat i korisniku prikazuje listu smještaja koji
zadovoljavaju postavljeni filter
UC2 – Rezerviraj smještaj
• Glavni sudionik: korisnik
• Cilj: Rezervirati željeni smještaj
• Sudionici: Aplikacija, Fuseki
• Preduvjet: Korisnik ima pristup Internet-u
• Rezultat: Smještaj je rezerviran
• Željeni scenarij:
1. Korisnik odabire smještaj
2. Sustav generira upit i šalje ga poslužitelju Fuseki
3. Fuseki obrađuje upit
4. Sustav javlja korisniku da je uspješno rezervirao smještaj
• Mogući drugi scenarij:
1. Ako korisnik odabere smještaj tipa Hotel ili Hostel
1.1 Korisnik odabire sobu
UC3 – Stvori smještaj
• Glavni sudionik: korisnik
• Cilj: Stvoriti novu ponudu smještaja
• Sudionici: Aplikacija, Fuseki
• Preduvjet: Korisnik ima pristup Internet-u
• Rezultat: Stvorena nova ponuda
26
• Željeni scenarij:
1. Korisnik odabire opciju za stvaranje novog smještaja
2. Korisnik puni formu za stvaranje novog smještaja
3. Sustav generira upit i šalje ga poslužitelju Fuseki
4. Fuseki obrađuje upit
5. Sustav vraća korisnika na početnu web stranicu aplikacije
UC4 – Ažuriraj smještaj
• Glavni sudionik: korisnik
• Cilj: Ažurirati ponuđeni smještaj
• Sudionici: Aplikacija, Fuseki
• Preduvjet: Korisnik ima pristup Internet-u
• Rezultat: Izbor smještaja je filtriran
• Željeni scenarij:
1. Korisnik odabire smještaj koji želi ažurirati
2. Korisnik uređuje formu za Ažuriranje smještaja
3. Sustav generira upit i šalje ga poslužitelju Fuseki
4. Fuseki obrađuje upit
5. Sustav vraća korisnika na početnu web stranicu aplikacije
UC5 – Izbriši smještaj
• Glavni sudionik: korisnik
• Cilj: Brisanje ponuđenog smještaja
• Sudionici: Aplikacija, Fuseki
• Preduvjet: Korisnik ima pristup Internet-u
• Rezultat: Brisanje smještaja iz ponude
• Željeni scenarij:
1. Korisnik odabire smještaj
27
2. Korisnik odabire opciju za brisanje
3. Sustav generira upit i šalje ga poslužitelju Fuseki
4. Fuseki obrađuje upit
5. Sustav vraća korisnika na početnu web stranicu aplikacije
UC6 – Izbriši sobu
• Glavni sudionik: korisnik
• Cilj: Brisanje ponuđene sobe hotela ili hostela
• Sudionici: Aplikacija, Fuseki
• Preduvjet: Korisnik ima pristup Internet-u
• Rezultat: Brisanje sobe iz ponude hotela ili hostela
• Željeni scenarij:
1. Korisnik odabire hotel ili hostel
2. Korisnik odabire sobu
3. Korisnik odabire opciju za brisanje
4. Sustav generira upit i šalje ga poslužitelju Fuseki
5. Fuseki obrađuje upit
6. Sustav vraća korisnika na početnu web stranicu aplikacije
28
Slika 5.1 Dijagram obrazaca uporabe
29
5.1.2. Sekvencijski dijagrami
Na slici 5.2 vidi se tok izvođenja filtriranja ponude smještaja. Korisnik odabire
opcije koje aplikacija poslije koristi za generiranje SPARQL upita. Od ponuđenih opcija,
samo su datumi dolaska i odlaska obavezne opcije. Ako ih korisnik ne odabere, aplikacija
automatski uzima trenutni datum kao početak i kraj trajanja rezervacije. Ostale opcije koje
se nude korisniku su lokacija, usluge koje smještaj može nuditi, npr. Wi-Fi, opcije
rezervacije, npr. rezervacije bez pologa i zvijezde smještaja. Iako filter nudi dvije opcije
filtriranja, sa i bez semantičkog rasuđivanja, jedina razlika u ponašanju aplikacije je na
koju će pristupnu točku poslužitelja Fuseki poslati HTTP GET zahtjev. Rezultat se zatim
parsira i prikazuje korisniku.
Slika 5.2 Sekvencijski dijagram filtriranja
Nakon filtriranja, korisnik odabire željeni smještaj. Slika 5.3 prikazuje ponašanje
aplikacije nakon odabira smještaja. Ovisno o tipu odabranog smještaja, aplikacija ima
razlike u ponašanju. Ako se korisnik odluči za smještaj tipa Hotel ili Hostel, aplikacija
generira SPARQL upit za dohvaćanje slobodnih soba u odabranom smještaju. Korisnik
tada odabire sobu koju želi rezervirati, a aplikacija generira SPARQL upit za dohvaćanje
rezerviranih termina sobe. Ako korisnik odabere neki drugi tip smještaja, aplikacija
preskače upit za dohvaćanje soba smještaja i odmah dohvaća rezervirane termine
smještaja. Nakon toga, ako korisnik želi rezervirati smještaj, aplikacija generira SPARQL
upit koji stvara nove RDF trojke koje definiraju rezervaciju smještaja i šalje HTTP POST
zahtjev poslužitelju Fuseki.
30
Slika 5.3 Sekvencijski dijagram rezerviranja smještaja
Stvaranje nove ponude smještaja započinje ispunjavanjem forme. Kada korisnik
ispuni formu, aplikacija generira niz SPARQL upita za stvaranje novih RDF trojki koje
opisuju novu ponudu i šalje ih poslužitelju Fuseki HTTP POST zahtjevom. Dva upita koja
se sigurno generiraju jesu upit za stvaranje smještaja i upit za stvaranje adrese. Upit za
stvaranje adrese se mora izvesti prije stvaranja samog smještaja jer je adresa instanca OWL
klase Address i mora postojati njen opis u ontologiji prije povezivanja sa smještajem.
Slično adresi, prije stvaranja trojki koje opisuju smještaj, aplikacija provjerava jesu li u
ontologiji opisani grad i država te ako nisu aplikacija generira upite za stvaranje trojki koje
ih opisuju.
31
Nakon što aplikacija osigura da je lokacija definirana u ontologiji, poslužitelju
šalje SPARQL upit koji definira trojke koje opisuju smještaj. Kada se novi smještaj opiše,
ako je taj smještaj tipa Hotel ili Hostel, aplikacija generira za svaku unesenu sobu poseban
upit koji definira RDF trojke i povezuje ih sa smještajem. Slika 5.4 prikazuje sekvencijski
dijagram opisanog postupka. Isti dijagram se može koristiti i za ažuriranje smještaja jer je
proces jednak, a jedina razlika je u generiranim upitima.
Slika 5.4 Sekvencijski dijagram stvaranja ponude smještaja
32
Nakon prikaza funkcionalnih zahtjeva i logike aplikacije, slijedi definicija
ontologije i prikaz slučajeva u kojima se primjenjuje semantičko rasuđivanje.
5.2. Ontologija aplikacije
Ontologija aplikacije je opisana uz pomoć alata Protégé, a opis klasa i svojstava
koje klase sadrže možemo vidjeti u Privitku B. U privitku također se nalaze i opisi instanci
klase Services nad kojima aplikacija koristi semantičko rasuđivanje prilikom filtriranja.
U nastavku je opisana ontologija i odnosi između klasa i instanci.
Klase Organization, Reservation, Services, Accommodation i Location,
prikazane na slici 5.5 su osnovne klase ontologije koje su definirane kao direktne podklase
osnovne klase Thing. Klasa Accommodation predstavlja središte ontologije i ostale
klase se definiraju za njeno opisivanje. Klasa Location se koristi za opisivanje lokacije
smještaja, klase Services i Reservation opisuju usluge koje smještaj nudi, odnosno
opcije rezerviranja. Klasa Organization predstavlja definiciju lanaca hotela.
Slika 5.5 Dijagram osnovnih OWL klasa
Na slici 5.6. prikazane su podklase klase Accommodation, odnosno tipovi
smještaja koje ontologija predstavlja. Klase Room i Apartment se mogu definirati kao
posebne ponude smještaja, ali i kao sastavni dijelovi hotela, hostela ili vile.
33
Slika 5.6 Dijagram OWL podklasa klase Accomodation
Lokacija je jedno od dijelova ontologije nad kojim se koristi semantičko
rasuđivanje. Klasa definira podklase Country, State, City i Address. Podklase su
međusobno povezane tranzitivnim svojstvom partOf. Tranzitivno svojstvo omogućava
semantičkom reasoner-u da adresu smještaja poveže s gradom, regijom i državom,
odnosno osigurava da u slučaju ako smještaj nema definiranu državu ili regiju u kojoj se
nalazi, korisnik pretraživanjem po državi ili regiji može doći do tog smještaja.
Slika 5.7 Dijagram OWL podklasa klase Loacation
Druga primjena semantičkog rasuđivanja su instance klase Services prikazane
na slici 5.8. Ontologijom je definirano da u slučaju ako smještaj eksplicitno opisuje ponude
Free_Wi-Fi, Free_Parking ili Inner_swimming_pool nudi i usluge Wi-Fi,
Parking i Swimming_pool. Isto se primjenjuje i u slučaju ako smještaj definira jedno
od usluga Breakfast, Lunch ili Room_service da nudi i uslugu Kitchen.
34
Slika 5.8 Dijagram OWL instanci klase Services
5.3. Konfiguracija poslužitelja Fuseki
Poslužitelj Fuseki se pokreće na istom stroju kao i aplikacija i konfiguriran je da
nudi dvije usluge. Obje usluge izvršavaju upite nad istom ontologijom, odnosno istim
OWL dokumentom i pristupa im se preko vrata (engl. port) 3030. Kôd 5.1 prikazuje
konfiguraciju prve usluge. Konfiguracija druge usluge se razlikuje od prve samo u imenu i
definiciji skupa podataka (engl. dataset) koje koristi. Ime druge usluge je fer2, a skup
podataka koje koristi je <#fer2>
<#service1> rdf:type fuseki:Service ;
fuseki:name "fer1" ;
fuseki:serviceQuery "sparql" ;
fuseki:serviceQuery "query" ;
fuseki:serviceUpdate "update" ;
fuseki:serviceUpload "upload" ;
fuseki:serviceReadWriteGraphStore "data" ;
fuseki:serviceReadGraphStore "get" ;
fuseki:dataset <#fer1> ;
.
Ime usluge definira ime pristupne točke na kojoj poslužitelj Fuseki nudi usluge, a
dataset ontologiju nad kojom izvršava upite. Kôd 5.2 prikazuje definiciju dataset-a
<#fer1>, a kôd 5.3 dataset-a <#fer2>. Može se primijetiti da je jedina razlika u
definiciji što dataset <#fer2> ne definira semantički reasoner.
Kôd 5.1 Konfiguracija usluge fer1
35
<#fer1> rdf:type ja:RDFDataset;
rdfs:label "fer" ;
ja:defaultGraph
[ rdfs:label "ontologija.owl" ;
a ja:InfModel ;
ja:content
[ ja:externalContent <file:Data/ontologija.owl> ];
ja:reasoner [
ja:reasonerURL
<http://jena.hpl.hp.com/2003/OWLMicroFBRuleReasoner>
];
];
.
<#fer2> rdf:type ja:RDFDataset;
rdfs:label "fer" ;
ja:defaultGraph
[ rdfs:label "ontologija.owl" ;
a ja:InfModel ;
ja:content
[ ja:externalContent <file:Data/ontologija.owl> ];
];
.
Cijela konfiguracijska datoteka poslužitelja priložena je kao Prilog C.
5.4. Generiranje SPARQL upita
Rad je nastavljen prikazivanjem upita koje aplikacija generira za dohvaćanje,
filtriranje, stvaranje, ažuriranje i brisanje ponuđenih smještaja. Radi pojednostavljenja, svi
prikazani upiti obrađuju podatke vezane uz smještaj tipa hotel.
Kôd 5.2 Definicija dataset-a <#fer1>
Kod 5.3 Definicija dataset-a <#fer2>
36
Svaki prikazani upit na početku definira skraćenice:
PREFIX Fer: <http://www.semanticweb.org/marin/ontologies/2017/3/diprad#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
Inicijalni pristup aplikaciji započinje generiranjem upita za dohvaćanje svih ponuda
smještaja s opisanim svojstvima koji je prikazan u kôdu 5.4.
SELECT
?hotel ?stars ?description
?services ?address ?thumbnail ?galery
WHERE {
?hotel a Fer:Hotel .
?hotel Fer:stars ?stars .
?hotel Fer:description ?description .
?hotel Fer:has ?services .
?hotel Fer:at ?address .
?hotel Fer:thumbnail ?thumbnail .
?hotel Fer:galery ?galery
}
Kôd 5.5 prikazuje generirani upit za filtriranje smještaja u Splitu s četiri zvjezdice
koji nudi uslugu Parking i dostupno je na datum 24.07.2017.
SELECT ?hotel ?stars ?description
?services ?address ?thumbnail ?galery
WHERE {
?hotel a Fer:Hotel .
?hotel Fer:stars ?stars .
?hotel Fer:description ?description .
?hotel Fer:has ?services .
?hotel Fer:thumbnail ?thumbnail .
?hotel Fer:galery ?galery .
?hotel Fer:at ?address .
?hotel Fer:partOf Fer:Split .
?hotel Fer:has Fer:Parking .
?hotel Fer:stars 4 .
?room Fer:in ?hotel .
FILTER NOT EXISTS {
Kôd 5.4 SPARQL upit za dohvačanje svih hotela s pripadnim svojstvima
37
?room Fer:reserved ?reserved .
FILTER(
?reserved = "2017-06-24T00:00:00"^^xsd:dateTime )
}
}
Nakon što korisnik postavi željene filtere i odabere željeni smještaj, aplikacija
generira upit sličan upitu prikaznim u kodu 5.4, samo što se ne traže svojstva svih hotela,
nego svojstva svih soba koje se nalaze u odabranom hotelu.
Kada korisnik odluči rezervirati smještaj, aplikacija generira upit:
INSERT DATA {
Fer:imeSobe Fer:reserved "2017-06-24T00:00:00"^^xsd:dateTime
}
U slučaju ako korisnik rezervira smještaj na više od jednog dana, generirani upit za
svaki dan rezervacije definira posebnu RDF trojku.
Upit za stvaranje novog smještaja je prikazan kôdom 5.6. Primjer pretpostavlja da
su grad i država već opisani ontologijom, a u slučaju da nisu, generirao bi se i upit za
definiranje trojki za njihov opis.
INSERT DATA {
Fer:Novi_hotel a Fer:Hotel .
Fer:Novi_hotel Fer:stars "5"^^xsd:integer .
Fer:Novi_hotel Fer:description "opis"^^xsd:string .
Fer:Novi_hotel Fer:at Fer:Unska_ul_3_10000_Zagreb_Croatia .
Fer:Novi_hotel Fer:partOf Fer:Croatia .
Fer:Novi_hotel Fer:partOf Fer:Zagreb .
Fer:Novi_hotel Fer:has Fer:Free_Wi-Fi .
}
Prikazani upit stvara novi hotel u Zagrebu koji nudi uslugu Free Wi-Fi. U slučaju
da novi smještaj nije tipa Hotel ili Hostel, upit bi također definirao i trojke za opis cijene i
broja ležaja. Za svaku sobu se definira poseban upit sličan upitu prikazanom kôdom 5.6.
Kôd 5.5 SPARQL upit za filtriranje ponđenog smještaja
Kôd 5.6 SPAQL upit za stvaranje novog sještaja
38
Pošto semantički web ne dozvoljava direktno mijenjanje instanci i svojstava
opisanih ontologijom, prilikom ažuriranja smještaja generira se DELETE INSERT upit
koji prvo briše trojke, a zatim stvara nove. Kôd 5.7 prikazuje generirani SPARQL upit za
ažuriranje hotela s definiranom jednom sobom i jednom uslugom. U slučaju da je hotelu
pridruženo više soba ili usluga, svaka bi se trebala izbrisati i ponovno dodati, iako se ne
mijenjaju.
DELETE {
Fer:ImeHotela Fer:description "opis"^^xsd:string .
Fer:ImeHotela Fer:stars "5"^^xsd:integer .
Fer:ImeHotela Fer:has Fer:Room_service .
Fer:ImeHotela Fer:has Fer:Free_Wi-Fi .
Fer:Room_1 Fer:in Fer:ImeHotela .
Fer:Room_1 Fer:bed "2"^^xsd:integer .
Fer:Room_1 Fer:description "opis sobe"^^xsd:string .
Fer:Room_1 Fer:price "200"^^xsd:integer .
}
INSERT {
Fer:ImeHotela Fer:description "novi opis"^^xsd:string .
Fer:ImeHotela Fer:stars "3"^^xsd:integer .
Fer:ImeHotela Fer:has Fer:Wi-Fi .
Fer:Room_1 Fer:in Fer:ImeHotela .
Fer:Room_1 Fer:bed "2"^^xsd:integer .
Fer:Room_1 Fer:description "opis sobe"^^xsd:string .
Fer:Room_1 Fer:price "150"^^xsd:integer .
}
WHERE {
Fer:ImeHotela a Fer:Hotel .
Fer:Wi-Fi a Fer:Services .
Fer: Room_1 a Fer:Room
}
Nakon prikaza glavnih SPARQL upita koje aplikacija generira, na kraju je dan
prikaz i opis korisničkog sučelja.
Kôd 5.7 SPARQL upi za ažuriranje smještaja
39
5.5. Korisničko sučelje
Slika 5.9 prikazuje glavno sučelje aplikacije. S lijeve strane se nalazi filter koji je
prisutan na svim sučeljima aplikacije. Veći dio sučelja zauzima prikaz ponuđenih
smještaja. Svaka ponuda sadrži osnovne informacije o smještaju kako bi se korisniku
olakšao odabir. Korisnik odabire smještaj klikom na karticu koja sadrži informacije, a ta ga
akcija preusmjerava na sučelje koje detaljnije opisuje odabranu opciju. Na dnu sučelja se
nalazi gumb New koje na klik preusmjerava korisnika na sučelje za stvaranje novog
smještaja.
Slika 5.9 Korisničko sučelje početne stranice
Filter koji aplikacija nudi, prikazan na slici 5.10, može se podijeliti na tri dijela.
Prvi dio nudi korisniku osnovne opcije za filtriranje smještaja, odnosno vrijeme, lokaciju i
luksuz. Drugi dio omogućava korisniku da odabere usluge i opcije rezervacije koje želi da
smještaj nudi, a u trećem dijelu korisnik može odabrati hoće li se filtriranje izvršiti uz
pomoć semantičkog reasoner-a ili ne.
40
Slika 5.10 Korisničko sučelje filtera
41
Slika 5.11 prikazuje sučelje za prikaz detalja odabranog smještaja. Na vrhu sučelja
se nalaze opis i usluge koje smještaj nudi. U središtu sučelja se nalazi galerija slika, a ispod
galerije su izlistane kartice slobodnih soba. Klikom na karticu sobe korisnik odabire sobu
koju želi rezervirati, a aplikacija ga preusmjerava na sučelje za prikaz detalja sobe. Na dnu
aplikacije se nalaze dva gumba, Edit koji korisnika preusmjerava na sučelje za ažuriranje
smještaja, i Remove koje briše smještaj iz ponude.
Slika 5.11 Korisničko sučelje za prikaz detalja hotela
42
Sučelje za prikaz detalja sobe na slici 5.12 se sastoji od zaglavlja koji sadrži
osnovne informacije o sobi. Ispod zaglavlja nalazi se detaljan opis sobe i kalendar koji
prikazuje datume kada je soba rezervirana. U sredini sučelja je, kao i na sučelju za prikaz
detalja smještaja, galerija slika sobe. Na dnu sučelja se nalze gumbe Reserve, koji na klik
stvara novu rezervaciju, i Remove, koji na klik briše sobu.
Slika 5.12 Korisničko sučelje za prikaz detalja sobe
Slika 5.13 prikazuje formu za stvaranje novog smještaja. Ovisno o odabranom tipu
smještaja, korisnik na dnu sučelja može opisivati sobe smještaja, odnosn klikom na gumb
Add room, može definirati više soba. Klikom na gumb Create korisnik stvara novi
smještaj, a aplikacija ga preusmjerava na početno sučelje aplikacije.
Sučelje za ažuriranje smještaja izgleda jednako kao i opisano sučelje, jedina razlika
je što je forma unaprijed popunjena definiranim vrijednostima.
43
Slika 5.13 Korisničko sučelje za stvaranje nove ponude smještaja
44
Zaključak
Zadatak ovog rada je bio definirati ontologiju koja opisuje podatke o smještaju za
iznajmljivanje. Osim toga, zadatak je bio i napraviti semantičku web-aplikaciju koja
omogućava korisnicima filtriranje ponude smještaja uz pomoć semantičkog rasuđivanja,
rezerviranje, ažuriranje i brisanje postojećeg smještaja i stvaranje novih ponuda.
Aplikacija je razvijena kao Node.js aplikacija s arhitekturalnim stilom Redux i
radnim okvirom React.js. Za rad aplikacije je bitan i poslužitelj Fuseki koji definira
pristupne točke RDF podatcima i izvođenje SPARQL upita s podrškom semantičkog
rasuđivanja. Za definiranje ontologije korišten je alat Protégé.
Aplikacija se jednostavno može proširiti na način da omogući korisnicima kupnju,
odnosno prodaju smještaja, a ontologija bi se mogla proširiti opisima i drugih usluga koje
ljudi nude, a ne samo iznajmljivanjem smještaja.
45
Literatura
[1] Semantic web, 17.08.2015., http://semanticweb.org/wiki/Main_Page.html,
16.06.2017.
[2] Umrežavanje sadržaja, Semantički web. Opis Web resursa., 2016.,
http://www.fer.unizg.hr/_download/repository/US-2016_06.pdf, 2016.
[3] Resource Description Framework (RDF) Model and Syntax Specification,
01.05.1999., https://www.w3.org/TR/PR-rdf-syntax/, 22.06.2017.
[4] OWL Web Ontology Language Guide, 12.11.2009. https://www.w3.org/TR/owl-
guide/, 17.06.2017.
[5] Umrežavanje sadržaja, Linked Data. SPARQL.¸ 2016.
http://www.fer.unizg.hr/_download/repository/US-2016_08.pdf, 2016.
[6] Developer Survey Results 2017,
https://insights.stackoverflow.com/survey/2017#technology-frameworks-libraries-
and-other-technologies, 22.03.2017.
[7] Introduction, 14.08.2015., http://redux.js.org/docs/introduction/, 01.12.2016.
[8] Hello World – React, 28.10.2015. https://facebook.github.io/react/docs/hello-
world.html, 18.07.2016.
46
Sažetak
Naslov:
Semantička web-aplikacija za iznajmljivanje smještaja
Sažetak:
Korištenjem ontologije za opisivanje podataka omogućava se semantičko rasuđivanje i
povezivanje web sadržaja. Rasuđivanje se izvršava zaključivanjem činjenica o podatcima
opisanim jezicima RDF, RDFS i OWL. Jedna od primjena semantičkog rasuđivanja je i
poboljšanje pretraživanja ponuda smještaja za iznajmljivanje, čime se ovaj rad bavi. Rad
opisuje postupak definiranja ontologije, izvođenje SPARQL upita i izradu semantičke
web-aplikacije. Kako bi se omogućilo izvođenje semantičkog reasoner-a, razvijena
aplikacija koristi poslužitelj Fuseki. Aplikacija je razvijana arhitekturalnim stilom Redux, a
korisničko sučelje je razvijeno uz pomoć radnog okvira React.js.
Ključne riječi:
Semantički web, ontologija, RDF, RDFS, OWL, SPARQL, Apache Jena Fuseki, Redux,
React.js, iznajmljivanje smještaja
47
Summary
Title:
A Semantic Web Application for Accommodation Rental
Summary:
Using ontology to describe the data, it enables semantic understanding and linking of web
content. Semantic reasoning is performed by taking out facts about data that is described
with RDF, RDFS and OWL languages. One of the application of semantic reasoning is to
improve the search for rental accommodation offers, which is what this paper deals with.
The paper describes the procedure for defining ontology, executing SPARQL queries and
creating a semantic web application. In order to enable semantic reasoner performance, the
developed application uses the Fuseki server. The application has been developed in Redux
architectural style, and the user interface has been developed with the help of the React.js
framework.
Key words:
Semantic web, ontology, RDF, RDFS, OWL, SPARQL, Apache Jena Fuseki, Redux,
React.js, accommodation rent
48
Skraćenice
WWW World Wide Web svjetska mreža
URL Uniform Resource Locator usklađeni lokator sadržaja
XML Extensible Markup Language jezik za označavanje podataka
URI Uniform Resource Identifier usklađeni idenitifikator sadržaja
RDF Resource Description Framework radni okvir za opis sadržaja
RDFS Resource Description Framework Schema shema za opis sadržaja
OWL Web Ontology Language jezik web ontologije
SPARQL SPARQL Protocol and RDF Query Language SPARQL protokol i upitni jezik
HTTP HyperText Transfer Protocol protokol za prijenos hiperteksta
JSON JavaScript Object Notation notacija JavaScript objekta
HTML HyperText Markup Language prezentacijski jezik za izadu
web stranica
49
Privitak A
Upute za pokretanje poslužitelja Fuseki
1. Sa stranice https://jena.apache.org/download/index.cgi preuzeti stabilnu verzuju
poslužitlja Apache Jena Fuseki
2. Raspakirati preuzetu datoteku na željenu lokaciju
3. Prilog B kopirati u novi dokument i dokument spremiti pod imenom ontologija.owl
u datoteku Data koja se nalazi u početnom direktoriju preuzetog poslužitelja
4. Sadržaj datoteke confog.ttl koja se nalzi u datoteci run zamijeniti prilogom C
5. Otovriti prozor naredbenog retka i pozicionirati se u početni direktorij preuzetog
poslužitelja
6. Pokrenuti poslužitelj naredbom fuseki-server –-update
Upute za pokretanje programskog rješenja rada
1. Sa stranice https://nodejs.org/en/ preuzeti instalaciju Node.js-a
2. Instalirati minimalno verziju v7.5.0
3. Otovriti prozor naredbenog retka i pozicionirati se u početni direktorij programskog
rješenja
4. Pokrenuti naredbu npm install
5. Pokrenuti aplikaciju naredbom npm start
6. U adresnoj traci web pretraživaća upisati localhost:8080
50
Privitak B
<?xmlversion="1.0"?>
<rdf:RDFxmlns="http://www.semanticweb.org/marin/ontologies/2017/3/diprad#
"
xml:base="http://www.semanticweb.org/marin/ontologies/2017/3/diprad"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:diprad="http://www.semanticweb.org/marin/ontologies/2017/3/diprad/"
>
<owl:Ontologyrdf:about="http://www.semanticweb.org/marin/ontologies/2017/
3/diprad"/>
<!--
/////////////////////////////////////////////////////////////////////////
//Annotationproperties
/////////////////////////////////////////////////////////////////////////
-->
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#has-->
<owl:AnnotationPropertyrdf:about="http://www.semanticweb.org/marin/ontolo
gies/2017/3/diprad#has"/>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#in-->
<owl:AnnotationPropertyrdf:about="http://www.semanticweb.org/marin/ontolo
gies/2017/3/diprad#in"/>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#partOf-->
<owl:AnnotationPropertyrdf:about="http://www.semanticweb.org/marin/ontolo
gies/2017/3/diprad#partOf"/>
<!--
51
/////////////////////////////////////////////////////////////////////////
//ObjectProperties
/////////////////////////////////////////////////////////////////////////
-->
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#at-->
<owl:ObjectPropertyrdf:about="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#at"/>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#has-->
<owl:ObjectPropertyrdf:about="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#has">
<rdf:typerdf:resource="http://www.w3.org/2002/07/owl#TransitiveProperty"/
>
</owl:ObjectProperty>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#in-->
<owl:ObjectPropertyrdf:about="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#in"/>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#partOf-->
<owl:ObjectPropertyrdf:about="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#partOf">
<rdf:typerdf:resource="http://www.w3.org/2002/07/owl#TransitiveProperty"/
>
</owl:ObjectProperty>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#sameAs-->
<owl:ObjectPropertyrdf:about="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#sameAs"/>
<!--
/////////////////////////////////////////////////////////////////////////
//Dataproperties
/////////////////////////////////////////////////////////////////////////
-->
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#bed-->
<owl:DatatypePropertyrdf:about="http://www.semanticweb.org/marin/ontologi
es/2017/3/diprad#bed">
52
<rdfs:subPropertyOfrdf:resource="http://www.w3.org/2002/07/owl#topDataPro
perty"/>
</owl:DatatypeProperty>
<!--
http://www.semanticweb.org/marin/ontologies/2017/3/diprad#description-->
<owl:DatatypePropertyrdf:about="http://www.semanticweb.org/marin/ontologi
es/2017/3/diprad#description">
<rdfs:subPropertyOfrdf:resource="http://www.w3.org/2002/07/owl#topDataPro
perty"/>
</owl:DatatypeProperty>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#galery-->
<owl:DatatypePropertyrdf:about="http://www.semanticweb.org/marin/ontologi
es/2017/3/diprad#galery"/>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#price-->
<owl:DatatypePropertyrdf:about="http://www.semanticweb.org/marin/ontologi
es/2017/3/diprad#price">
<rdfs:subPropertyOfrdf:resource="http://www.w3.org/2002/07/owl#topDataPro
perty"/>
</owl:DatatypeProperty>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#reserved-->
<owl:DatatypePropertyrdf:about="http://www.semanticweb.org/marin/ontologi
es/2017/3/diprad#reserved">
<rdfs:subPropertyOfrdf:resource="http://www.w3.org/2002/07/owl#topDataPro
perty"/>
</owl:DatatypeProperty>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#stars-->
<owl:DatatypePropertyrdf:about="http://www.semanticweb.org/marin/ontologi
es/2017/3/diprad#stars">
<rdfs:subPropertyOfrdf:resource="http://www.w3.org/2002/07/owl#topDataPro
perty"/>
</owl:DatatypeProperty>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#thumbnail--
>
53
<owl:DatatypePropertyrdf:about="http://www.semanticweb.org/marin/ontologi
es/2017/3/diprad#thumbnail"/>
<!--
/////////////////////////////////////////////////////////////////////////
//Classes
/////////////////////////////////////////////////////////////////////////
-->
<!--
http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Accommodation--
>
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Accommodation">
<owl:equivalentClass>
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#at"/>
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#Address"/>
</owl:Restriction>
</owl:equivalentClass>
<owl:equivalentClass>
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#has"/>
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#Reservation"/>
</owl:Restriction>
</owl:equivalentClass>
<owl:equivalentClass>
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#has"/>
54
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#Services"/>
</owl:Restriction>
</owl:equivalentClass>
<owl:equivalentClass>
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#partOf"/>
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#Location"/>
</owl:Restriction>
</owl:equivalentClass>
<owl:equivalentClass>
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#partOf"/>
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#Organization"/>
</owl:Restriction>
</owl:equivalentClass>
</owl:Class>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Address-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Address">
<owl:equivalentClass>
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#partOf"/>
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#City"/>
</owl:Restriction>
</owl:equivalentClass>
55
<rdfs:subClassOfrdf:resource="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#Location"/>
</owl:Class>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Apartment--
>
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Apartment">
<owl:equivalentClass>
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#in"/>
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#Hotel"/>
</owl:Restriction>
</owl:equivalentClass>
<owl:equivalentClass>
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#in"/>
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#Villa"/>
</owl:Restriction>
</owl:equivalentClass>
<rdfs:subClassOfrdf:resource="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#Accommodation"/>
</owl:Class>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#City-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#City">
<owl:equivalentClass>
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#partOf"/>
56
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#State"/>
</owl:Restriction>
</owl:equivalentClass>
<rdfs:subClassOfrdf:resource="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#Location"/>
</owl:Class>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Country-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Country">
<rdfs:subClassOfrdf:resource="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#Location"/>
</owl:Class>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Hostel-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Hostel">
<rdfs:subClassOfrdf:resource="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#Accommodation"/>
</owl:Class>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Hotel-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Hotel">
<rdfs:subClassOfrdf:resource="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#Accommodation"/>
</owl:Class>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#HotelChain-
->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#HotelChain">
<rdfs:subClassOfrdf:resource="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#Organization"/>
</owl:Class>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#House-->
57
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#House">
<rdfs:subClassOfrdf:resource="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#Accommodation"/>
</owl:Class>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Location-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Location"/>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Lodge-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Lodge">
<rdfs:subClassOfrdf:resource="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#Accommodation"/>
</owl:Class>
<!--
http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Organization-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Organization"/>
<!--
http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Reservation-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Reservation"/>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Room-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Room">
<owl:equivalentClass>
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#in"/>
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#Hostel"/>
</owl:Restriction>
</owl:equivalentClass>
<owl:equivalentClass>
58
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#in"/>
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#Hotel"/>
</owl:Restriction>
</owl:equivalentClass>
<owl:equivalentClass>
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#in"/>
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#House"/>
</owl:Restriction>
</owl:equivalentClass>
<owl:equivalentClass>
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#in"/>
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#Lodge"/>
</owl:Restriction>
</owl:equivalentClass>
<rdfs:subClassOfrdf:resource="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#Accommodation"/>
</owl:Class>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Services-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Services"/>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#State-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#State">
<owl:equivalentClass>
59
<owl:Restriction>
<owl:onPropertyrdf:resource="http://www.semanticweb.org/marin/ontologies/
2017/3/diprad#partOf"/>
<owl:someValuesFromrdf:resource="http://www.semanticweb.org/marin/ontolog
ies/2017/3/diprad#Country"/>
</owl:Restriction>
</owl:equivalentClass>
<rdfs:subClassOfrdf:resource="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#Location"/>
</owl:Class>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Villa-->
<owl:Classrdf:about="http://www.semanticweb.org/marin/ontologies/2017/3/d
iprad#Villa">
<rdfs:subClassOfrdf:resource="http://www.semanticweb.org/marin/ontologies
/2017/3/diprad#Accommodation"/>
</owl:Class>
<!--
/////////////////////////////////////////////////////////////////////////
//Individuals
/////////////////////////////////////////////////////////////////////////
-->
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Breakfast--
>
<owl:NamedIndividualrdf:about="http://www.semanticweb.org/marin/ontologie
s/2017/3/diprad#Breakfast">
<rdf:typerdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3
/diprad#Services"/>
<hasrdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3/dipr
ad#Kitchen"/>
</owl:NamedIndividual>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Free_Wi-Fi-
->
60
<owl:NamedIndividualrdf:about="http://www.semanticweb.org/marin/ontologie
s/2017/3/diprad#Free_Wi-Fi">
<rdf:typerdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3
/diprad#Services"/>
<hasrdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3/dipr
ad#Wi-Fi"/>
</owl:NamedIndividual>
<!--
http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Free_canceling-
->
<owl:NamedIndividualrdf:about="http://www.semanticweb.org/marin/ontologie
s/2017/3/diprad#Free_canceling">
<rdf:typerdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3
/diprad#Reservation"/>
</owl:NamedIndividual>
<!--
http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Free_parking-->
<owl:NamedIndividualrdf:about="http://www.semanticweb.org/marin/ontologie
s/2017/3/diprad#Free_parking">
<rdf:typerdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3
/diprad#Services"/>
<hasrdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3/dipr
ad#Parking"/>
</owl:NamedIndividual>
<!--
http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Inner_swimming_
pool-->
<owl:NamedIndividualrdf:about="http://www.semanticweb.org/marin/ontologie
s/2017/3/diprad#Inner_swimming_pool">
<rdf:typerdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3
/diprad#Services"/>
<hasrdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3/dipr
ad#Swimming_pool"/>
</owl:NamedIndividual>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Kitchen-->
61
<owl:NamedIndividualrdf:about="http://www.semanticweb.org/marin/ontologie
s/2017/3/diprad#Kitchen">
<rdf:typerdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3
/diprad#Services"/>
</owl:NamedIndividual>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Lunch-->
<owl:NamedIndividualrdf:about="http://www.semanticweb.org/marin/ontologie
s/2017/3/diprad#Lunch">
<rdf:typerdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3
/diprad#Services"/>
<hasrdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3/dipr
ad#Kitchen"/>
</owl:NamedIndividual>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#No_deposit-
->
<owl:NamedIndividualrdf:about="http://www.semanticweb.org/marin/ontologie
s/2017/3/diprad#No_deposit">
<rdf:typerdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3
/diprad#Reservation"/>
<hasrdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3/dipr
ad#Free_canceling"/>
</owl:NamedIndividual>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Parking-->
<owl:NamedIndividualrdf:about="http://www.semanticweb.org/marin/ontologie
s/2017/3/diprad#Parking">
<rdf:typerdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3
/diprad#Services"/>
</owl:NamedIndividual>
<!--
http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Room_service-->
<owl:NamedIndividualrdf:about="http://www.semanticweb.org/marin/ontologie
s/2017/3/diprad#Room_service">
<rdf:typerdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3
/diprad#Services"/>
62
<hasrdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3/dipr
ad#Kitchen"/>
</owl:NamedIndividual>
<!--
http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Swimming_pool--
>
<owl:NamedIndividualrdf:about="http://www.semanticweb.org/marin/ontologie
s/2017/3/diprad#Swimming_pool">
<rdf:typerdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3
/diprad#Services"/>
</owl:NamedIndividual>
<!--http://www.semanticweb.org/marin/ontologies/2017/3/diprad#Wi-Fi-->
<owl:NamedIndividualrdf:about="http://www.semanticweb.org/marin/ontologie
s/2017/3/diprad#Wi-Fi">
<rdf:typerdf:resource="http://www.semanticweb.org/marin/ontologies/2017/3
/diprad#Services"/>
</owl:NamedIndividual>
63
Privitak C
# Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0
## Fuseki Server configuration file.
@prefix : <#> .
@prefix fuseki: <http://jena.apache.org/fuseki#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix ja: <http://jena.hpl.hp.com/2005/11/Assembler#> .
[] rdf:type fuseki:Server ;
fuseki:services (
<#service1>
<#service2>
) .
# [] ja:loadClass "com.hp.hpl.jena.sdb.SDB" .
<#service1> rdf:type fuseki:Service ;
fuseki:name "fer1" ;
fuseki:serviceQuery "sparql" ;
fuseki:serviceQuery "query" ;
fuseki:serviceUpdate "update" ;
fuseki:serviceUpload "upload" ;
fuseki:serviceReadWriteGraphStore "data" ;
fuseki:serviceReadGraphStore "get" ;
fuseki:dataset <#fer1> ;
.
<#fer1> rdf:type ja:RDFDataset;
rdfs:label "fer" ;
ja:defaultGraph
[ rdfs:label "ontologija.owl" ;
64
a ja:InfModel ;
ja:content [ja:externalContent <file:Data/ontologija.owl> ];
ja:reasoner [
ja:reasonerURL
<http://jena.hpl.hp.com/2003/OWLMicroFBRuleReasoner>
];
];
.
<#service2> rdf:type fuseki:Service ;
fuseki:name "fer2" ;
fuseki:serviceQuery "sparql" ;
fuseki:serviceQuery "query" ;
fuseki:serviceUpdate "update" ;
fuseki:serviceUpload "upload" ;
fuseki:serviceReadWriteGraphStore "data" ;
fuseki:serviceReadGraphStore "get" ;
fuseki:dataset <#fer2> ;
.
<#fer2> rdf:type ja:RDFDataset;
rdfs:label "fer" ;
ja:defaultGraph
[ rdfs:label "ontologija.owl" ;
a ja:InfModel ;
ja:content [ja:externalContent <file:Data/ontologija.owl> ];
];
.