root/trunk/java/org.semanticdesktop.nepomuk.comp.pimoservice.test/src/org/semanticdesktop/nepomuk/comp/pimoservice/test/PimoOntologyTest.java

Revision 4467, 20.0 kB (checked in by leosauermann, 10 months ago)

services:added localdataalignment interface
pimoclient: fixed language problem when openlinkeddata. removed dependency to util as of problems in WAR installation

Line 
1/**
2 *
3 */
4package org.semanticdesktop.nepomuk.comp.pimoservice.test;
5
6import java.io.FileInputStream;
7import java.io.IOException;
8import java.io.InputStream;
9import java.util.Collection;
10
11import junit.framework.TestCase;
12
13import org.ontoware.aifbcommons.collection.ClosableIterator;
14import org.ontoware.rdf2go.RDF2Go;
15import org.ontoware.rdf2go.model.Model;
16import org.ontoware.rdf2go.model.ModelSet;
17import org.ontoware.rdf2go.model.Statement;
18import org.ontoware.rdf2go.model.Syntax;
19import org.ontoware.rdf2go.model.node.LanguageTagLiteral;
20import org.ontoware.rdf2go.model.node.Node;
21import org.ontoware.rdf2go.model.node.PlainLiteral;
22import org.ontoware.rdf2go.model.node.URI;
23import org.ontoware.rdf2go.model.node.Variable;
24import org.ontoware.rdf2go.model.node.impl.PlainLiteralImpl;
25import org.ontoware.rdf2go.model.node.impl.URIImpl;
26import org.ontoware.rdf2go.vocabulary.RDF;
27import org.ontoware.rdf2go.vocabulary.RDFS;
28import org.semanticdesktop.nepomuk.comp.pimoservice.PimoQuery;
29import org.semanticdesktop.nepomuk.comp.pimoservice.client.ClientSession;
30import org.semanticdesktop.nepomuk.comp.pimoservice.client.PimoClient;
31import org.semanticdesktop.nepomuk.comp.pimoservice.impl.PimoServiceImpl;
32import org.semanticdesktop.nepomuk.mockup.MockupNepomukServices;
33import org.semanticdesktop.nepomuk.util.TestTool;
34import org.semanticdesktop.services.NepomukServices;
35import org.semanticdesktop.services.ServiceNotFoundException;
36import org.semanticdesktop.services.pimoservice.PimoService;
37import org.semanticdesktop.services.rdfrepository.RDF2GoRepository;
38import org.semanticdesktop.services.rdfrepository.RDFRepositoryCommon;
39import org.semanticdesktop.services.vocabulary.NAO;
40import org.semanticdesktop.services.vocabulary.NCAL;
41import org.semanticdesktop.services.vocabulary.NCO;
42import org.semanticdesktop.services.vocabulary.PIMO;
43
44/**
45 * A JUnit test that runs common commands realizing a scenario.
46 * The scenario under focus is Claudia and her trip to Belfast.
47 * She annotates her co-worker Dirk, etc.
48 *
49 * This JUnit test serves as a tutorial how to program using the
50 * PIMO Service and the PIMO Ontology.
51 * @author Martin Klinkigt
52 *
53 */
54public class PimoOntologyTest extends TestCase {
55       
56        NepomukServices services;
57        PimoService pimoservice;
58        PimoClient pimoclient;
59        PimoQuery query;
60        ClientSession session;
61        RDF2GoRepository repository;
62        ModelSet main;
63       
64        final String claudiaNameSpace = "http://www.sap.com/people/claudia#";
65        final String claudiaEmail = "claudi-1@csc.kth.se";
66        final String claudiaPimoUri = "http://www.sap.com/people/claudia#PIMO";
67        final String claudiaUserUri = "http://www.sap.com/people/claudia#Claudia";
68
69        /* (non-Javadoc)
70         * @see junit.framework.TestCase#setUp()
71         */
72        protected void setUp() throws Exception {
73                TestTool.setFullLogging();
74                super.setUp();
75        }
76
77        /* (non-Javadoc)
78         * @see junit.framework.TestCase#tearDown()
79         */
80        protected void tearDown() throws Exception {
81                super.tearDown();
82        }
83       
84        /**
85         * A walkthrough of many things that happen in Claudia's scenario of
86         * working with Dirk and going to Belfast
87         */
88        public void testClaudiasScenario() throws Exception {
89                // initialize PIMO for Claudia
90                MockupNepomukServices mockup = new MockupNepomukServices();
91                RDF2GoRepository repository = mockup.getRdf2gorepository();
92               
93                // Replace normal mockup configuration with correct uris for this test.
94        // This is done BEFORE the first call to mockup.getPimoService(),
95        // because otherwise the mockup will use its own configuration for
96        // claudia.
97        {
98            ModelSet ms = repository.getRepository(RDFRepositoryCommon.CONFIG_REPOSITORY_ID);
99            Model m = ms.getModel(new URIImpl(RDFRepositoryCommon.DEFAULTGRAPH_URI));
100            // m is not the default Model from the config repository (=not the main repository)
101            m.open();
102            InputStream in  = getClass().getResourceAsStream("claudiaconfig.n3");
103            try  {
104                try {
105                    m.readFrom(in, Syntax.Turtle);
106                } finally {
107                    in.close();
108                }
109            } catch (IOException x)
110            {
111                throw new ServiceNotFoundException("Cannot initialize pimo config: "+x, x);
112            }
113            m.close();
114        }
115
116        // get the other Services needed to interact with PIMO
117                pimoclient = mockup.getPimoClient();
118                query = pimoclient.getPimoQuery();
119                main = pimoclient.getMainRepository();
120                session = pimoclient.createSession();
121        ModelSet workmodelset = session.getWorkModelSet();
122       
123                // first tests on PIMO-Client related to CONFIGURATION values
124                // get Identifier for Claudia from PimoClient,
125                URI claudiaURI = pimoclient.getUserUri();
126                assertEquals(claudiaUserUri,claudiaURI.toString());
127                assertEquals(claudiaNameSpace,pimoclient.getUserNamespace().toString());
128               
129        // get Identifier for Claudias PIMO from PimoClient
130                URI claudiaPimo = pimoclient.getPimoUri();
131                assertEquals(claudiaPimoUri,claudiaPimo.toString());
132               
133                // load RDF about Dirk as NCO PersonContact from file
134                // as if Claudia kept an Address book and had a vCard entry for Dirk.
135        // In Nepomuk, this would have been crawled by DataWrapper Aperture
136        // already and put into the "main" RDFRepository.
137                // file://home/claudia/dirk.vcf#dirk
138                URI dirkPersonContact = new URIImpl("file://home/claudia/dirk.vcf#dirk");
139        Model mDirk = main.getModel(dirkPersonContact);
140        mDirk.open();
141        InputStream inDirk  = getClass().getResourceAsStream("dirk.n3");
142        try  {
143            try {
144                mDirk.readFrom(inDirk, Syntax.Turtle);
145            } finally {
146                inDirk.close();
147            }
148        } catch (IOException x)
149        {
150            throw new ServiceNotFoundException("Cannot load Dirk: "+x, x);
151        }
152        inDirk.close();
153                       
154                // Create a PIMO:Person from the NCO:PersonContact.
155        // The dirkPimo URI is the unique identifier for the Person Dirk
156        // on Claudias system. It is then connected to the URI in the
157        // vCard using the PIMO:groundingOccurrence relation.
158        // We call this process "rebirth" as Dirk is now reborn as PIMO Thing,
159        // or "thingification".
160                URI dirkPimo = session.createResourceFromGroundingOccurence(dirkPersonContact, "Dirk Hagemann", PIMO.Person);
161                session.commit();
162        // Thingification also copies the identifiers of the occurrence to the Thing,
163        // so that other services can find Things based on nao:identifier and its sub-properties.
164                assertTrue(main.containsStatements(Variable.ANY, dirkPimo, NAO.identifier, new PlainLiteralImpl("dirk@sap.com")));
165               
166        // dirkPimo is the unique identifier but does not have many properties.
167        // dirkPersonContact has properties defined in the address book.
168        // Both represent the same entity, the user now wants to see all
169        // facts about the Person Dirk in an integrated view
170
171                // load resource closure about dirk, fully inferred, the facts about his grounding occurrence
172                // are facts about dirk as person
173                session.bufferResourceClosure(dirkPimo, PIMO.GroundingClosure);
174
175                //integratedView.dump();
176                // assert that the name, address, email is taken from the grounding
177                assertTrue(workmodelset.containsStatements(Variable.ANY, dirkPimo, NCO.nameFamily, new PlainLiteralImpl("Hagemann")));
178                assertTrue(workmodelset.containsStatements(Variable.ANY, dirkPimo, NCO.nameGiven, new PlainLiteralImpl("Dirk")));
179               
180                // User tries to edit the facts about the grounding - this is forbidden
181                try {
182            workmodelset.removeStatement(PIMO.GroundingClosure, dirkPimo, NCO.nameGiven, new PlainLiteralImpl("Dirk"));
183                        fail("can remove a fact inferred from the GroundingClosure");
184                } catch (Exception e) {
185                        // it works
186                }
187               
188                // find out somehow which triples of the resource closure integratedView
189                // can be edited (which were created by
190                // PIMO or NEPOMUK) and which come from NIE
191                // See ModelSetDiff. Works over the contextURI
192               
193                // Edit facts that have been said about the dirkPimo.
194        {
195            // the complicated way:
196            // First get a valid contextURI from the session.
197                URI contextURI = session.getWorkModel().getContextURI();
198            // then add to the context
199                URI dirkSAPPage = new URIImpl("http://www.sap.com/people/DirkHagemann");
200                // Add the new fact using the workmodelset and the new context URI
201                workmodelset.addStatement(contextURI, dirkPimo, PIMO.referencingOccurrence, dirkSAPPage);
202           
203            // The same can be done without caring for context by using the magic
204            // model directly, which adds everything to the work model by default
205            URI dirkID = new URIImpl("http://id.sap.com/person/1650");
206            session.getMagicModel().addStatement(dirkPimo, PIMO.hasOtherRepresentation, dirkID);
207            assertEquals("context uri stays the same until commit", contextURI, session.getWorkModel().getContextURI());
208            assertEquals("the magicmodel has the same context as the workmodel, for convenience",
209                session.getWorkModel().getContextURI(), session.getMagicModel().getContextURI());
210   
211                // we must commit the session to add the statements in the repository
212            // committing the session will not flush the buffers!
213            // The closure is still buffered.
214                session.commit();
215           
216            assertTrue(main.containsStatements(contextURI, dirkPimo, PIMO.referencingOccurrence, new URIImpl("http://www.sap.com/people/DirkHagemann")));
217            assertTrue(main.containsStatements(contextURI, dirkPimo, PIMO.hasOtherRepresentation, dirkID));
218                assertTrue(main.containsStatements(contextURI, dirkPimo, PIMO.referencingOccurrence, dirkSAPPage));
219                assertTrue(main.containsStatements(contextURI, dirkPimo, PIMO.hasOtherRepresentation, dirkID));
220        }
221                // create claudia:InitialMeetinginBelfast
222                URI belfastMeeting = session.createResource("Initial Meeting in Belfast", PIMO.Meeting);
223                session.commit();
224
225                // get possible Properties
226                Collection<URI> meetProps = query.getPossiblePropertiesForThing(belfastMeeting.toString(), true, true);
227                assertFalse(meetProps.contains(NCAL.dtstart));
228                assertFalse(meetProps.contains(NCAL.categories));
229                assertFalse(meetProps.contains(NCAL.contact));
230                assertFalse(meetProps.contains(NCAL.location));
231                assertFalse(meetProps.contains(NCAL.duration));
232               
233                // add to befastMeeting the type NCAL.Event to get NCAL properties
234                session.getMagicModel().addStatement(belfastMeeting, RDF.type, NCAL.Event);
235        // this implicitly created a new context, which has to be committed.
236                session.commit();
237               
238                // HELP the user editing claudia:InitialMeetinginBelfast
239                // query for a list of properties that can be added to claudia:InitialMeetinginBelfast
240                // This list contains PIMO properties but also NIE/NCAL properties!
241        if (1==2) // TODO: this is broken at the moment
242        {
243                meetProps = query.getPossiblePropertiesForThing(belfastMeeting.toString(), true, true);
244                assertTrue(meetProps.contains(NCAL.dtstart));
245                assertTrue(meetProps.contains(NCAL.categories));
246                assertTrue(meetProps.contains(NCAL.contact));
247                // Location is not one of them, rather PIMO.hasLocation should be used
248        // assertTrue(meetProps.contains(NCAL.location));
249                assertTrue(meetProps.contains(NCAL.duration));
250        }
251               
252                // select three NCAL properties to be added to the claudia:InitialMeetinginBelfast
253                PlainLiteral belfastLocation = new PlainLiteralImpl("Hotel Belfast");
254                PlainLiteral belfastStart = new PlainLiteralImpl("20070304T230000");
255                PlainLiteral belfastDuration = new PlainLiteralImpl("DURATION:PT1H0M0S");
256                URI belfastDate = session.createResource(NCAL.NcalDateTime);
257                session.getMagicModel().addStatement(belfastDate, NCAL.dateTime, belfastStart);
258        session.getMagicModel().addStatement(belfastMeeting, NCAL.duration, belfastDuration);
259        session.getMagicModel().addStatement(belfastMeeting, NCAL.location, belfastLocation);
260                session.commit();
261               
262                // add some fact about belfast may be automaticaly with local data alignment
263                // TODO asserts
264               
265                // (create class flight)
266                URI flight = session.createClass("Flight", PIMO.Event);
267               
268                // (create flights)
269                URI LHL4573 = session.createResource("LHL 4573 - Frankfurt - Belfast", flight);
270                URI LHL7452 = session.createResource("LHL 7452 - Belfast - Frankfurt", flight);
271               
272                // add pimo:hasPart to claudia:InitialMeetinginBelfast for the flights
273                Model wk = session.getWorkModel();
274                wk.addStatement(belfastMeeting, PIMO.hasPart, LHL4573);
275                wk.addStatement(belfastMeeting, PIMO.hasPart, LHL7452);
276               
277                // SAVE
278                session.commit();
279                // is it saved?
280                assertTrue(main.containsStatements(Variable.ANY, belfastMeeting, RDF.type, PIMO.Meeting));
281                assertTrue(main.containsStatements(Variable.ANY, flight, RDFS.subClassOf, PIMO.Event));
282                assertTrue(main.containsStatements(Variable.ANY, LHL4573, RDF.type, flight));
283                assertTrue(main.containsStatements(Variable.ANY, LHL7452, RDF.type, flight));
284                // check inferencing
285                assertTrue(main.containsStatements(Variable.ANY, LHL4573, PIMO.partOf, belfastMeeting));
286                assertTrue(main.containsStatements(Variable.ANY, LHL7452, PIMO.partOf, belfastMeeting));
287               
288        // Claudia now represents the City of Belfast
289                // create Belfast, implicitly also a new context in the clientsession
290                URI belfast = session.createResource("Belfast", PIMO.City);
291               
292                // add pimo:hasLocation to claudia:InitialMeetinginBelfast to Belfast
293                session.getMagicModel().addStatement(belfastMeeting, PIMO.hasLocation, belfast);
294               
295                // link Belfast with Wikipedia entry about Belfast using
296                // pimo:referencingOccurrence
297        // This indicates that Claudia's Belfast "is the same concept as described
298        // on that resource I refer to".
299        // See also this paper for more deliberate use:
300        // "PIMO Population and Semantic Annotation for the Gnowsis Semantic Desktop"
301        // http://ftp.informatik.rwth-aachen.de/Publications/CEUR-WS/Vol-202/SEMDESK2006_0008.pdf
302        session.getMagicModel().addStatement(belfast,PIMO.referencingOccurrence,new URIImpl("http://en.wikipedia.org/wiki/Belfast"));
303               
304                // link Belfast with DBPEdia entry about Belfast using
305                // pimo:hasOtherRepresentation
306                // http://dbpedia.org/resource/Belfast
307        // This indicates that there is another ontology that represents the
308        // same concept as Claudia's Belfast.
309        session.getMagicModel().addStatement(belfast,PIMO.hasOtherRepresentation,new URIImpl("http://dbpedia.org/resource/Belfast"));
310       
311        // commit this session
312        session.commit();
313               
314                // BONUS: load belfast information including hasOtherRepresentation
315                // closure using linked data on HTTP GET (accept:rdf) on http://dbpedia.org/resource/Belfast
316        {
317            // Assuming we forgot above lines and only remember Belfast.
318            session.bufferOpenLinkedData(belfast);
319           
320            // now assert the facts from DBPedia are also facts about claudia's Belfast
321            // look in the workmodelset and see that it contains statements
322            // with non English literals
323            String nonEnglishLiteral = "";
324            boolean englishLiteral = false;
325            ClosableIterator<? extends Statement> iter = null;
326            try {
327                iter = workmodelset.findStatements(Variable.ANY, belfast, Variable.ANY, Variable.ANY);
328                while (iter.hasNext()) {
329                        Statement s = iter.next();
330                        Node node = s.getObject();
331                        if (node instanceof LanguageTagLiteral) {
332                                LanguageTagLiteral literal = node.asLanguageTagLiteral();
333                                if(literal.getLanguageTag().equals("en")) {
334                                        englishLiteral = true;
335                                } else {
336                                        nonEnglishLiteral +=literal.getLanguageTag()+",";
337                                }
338                        }
339                }
340            } finally {
341                iter.close();
342            }
343            assertTrue("Result contains a statement about Belfast which is English",englishLiteral);
344            assertTrue("Result should contain statement about Belfast which is not English",nonEnglishLiteral.length()>0);
345           
346            // we only want statements in the language which Claudia speaks
347            // filter belfast data based on the language of the user configured in
348            // pimoclient
349            session.setLanguageFilter(true);
350           
351            nonEnglishLiteral = "";
352            englishLiteral = false;
353            try {
354                iter = workmodelset.findStatements(Variable.ANY, belfast, Variable.ANY, Variable.ANY);
355                while (iter.hasNext()) {
356                        Statement s = iter.next();
357                        Node node = s.getObject();
358                        if (node instanceof LanguageTagLiteral) {
359                                LanguageTagLiteral literal = node.asLanguageTagLiteral();
360                                if(literal.getLanguageTag().equals("en")) {
361                                        englishLiteral = true;
362                                } else {
363                            nonEnglishLiteral +=literal.getLanguageTag()+",";
364                                }
365                        }
366                }
367            } finally {
368                iter.close();
369            }
370            assertTrue("Result contains a statement about Belfast which is English",englishLiteral);
371            assertTrue("Result contains a statement about Belfast which is not English, languages are: "+nonEnglishLiteral,nonEnglishLiteral.length()==0);
372
373        }
374               
375                // on the linked data, show an integratd view of belfast,
376                // including its relation with the meeting (location)
377                // and the english rdfs:comment from dbpedia
378                // TODO
379       
380        // now we tag some local files
381        // first we need the aperture crawl result in the repository.
382        main.open();
383        main.readFrom(getClass().getResourceAsStream("ClaudiaDocumentsCrawl.trix"),Syntax.Trix);
384        // okay, now we must create a tag. But Claudia makes a mistake.
385        // for taging she must create a nao:Tag but she makes something better ...
386        URI cid = session.createResource("CID", PIMO.Project);
387        session.commit();
388        // this is not a tag, but Claudia tries to add it to a local file
389        URI CIDJobOffer = new URIImpl("file:/D:/Nepomuk/workspace/claudia_stern/documents/projects/CID/Job%20Offer%20CID%20Training.doc");
390        session.addTag(CIDJobOffer, cid);
391        session.commit();
392        // nothing went wrong, because the system makes cid to a nao:Tag
393        // and created a PIMO.Document from the URI to the file system
394        // This is better because we don't only have a simple tag with text
395        // but the whole hierarchy. So we also know, that this file is a
396        // document from a project.
397       
398        // we don't know the uri if this thing, so try to get it
399        URI CIDJobOfferDocument = null;
400        ClosableIterator<? extends Statement> iter = null;
401        try {
402                iter = main.findStatements(Variable.ANY, Variable.ANY, NAO.hasTag, cid);
403                for (int i = 0; iter.hasNext(); i++) {
404                        if (i==0) {
405                                // the first entry
406                                CIDJobOfferDocument = iter.next().getSubject().asURI();
407                                assertFalse(CIDJobOfferDocument==null);
408                        } else {
409                                // something went wrong.
410                                fail("There are more than one thing, which has the tag: "+cid);
411                        }
412                }
413        } finally {
414                iter.close();
415        }
416        assertTrue(main.containsStatements(Variable.ANY, CIDJobOfferDocument, NAO.hasTag, cid));
417        assertTrue(main.containsStatements(Variable.ANY, CIDJobOfferDocument, PIMO.groundingOccurrence, CIDJobOffer));
418        // now we tag Dirk with this cid tag
419        session.addTag(dirkPimo, cid);
420        session.commit();
421        assertTrue(main.containsStatements(Variable.ANY, dirkPimo, NAO.hasTag, cid));
422        // for more information about tagging see:
423        // https://dev.nepomuk.semanticdesktop.org/wiki/ClientSession
424        }
425       
426
427}
Note: See TracBrowser for help on using the browser.