1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 package complex.unoxml;
29 
30 import helper.StreamSimulator;
31 
32 import com.sun.star.uno.UnoRuntime;
33 import com.sun.star.uno.XComponentContext;
34 import com.sun.star.lang.XMultiServiceFactory;
35 import com.sun.star.lang.XServiceInfo;
36 import com.sun.star.lang.IllegalArgumentException;
37 import com.sun.star.lang.WrappedTargetException;
38 import com.sun.star.lang.WrappedTargetRuntimeException;
39 import com.sun.star.beans.XPropertySet;
40 import com.sun.star.beans.Pair;
41 import com.sun.star.beans.StringPair;
42 import com.sun.star.container.XEnumeration;
43 import com.sun.star.container.ElementExistException;
44 import com.sun.star.container.NoSuchElementException;
45 import com.sun.star.io.XInputStream;
46 import com.sun.star.io.XOutputStream;
47 import com.sun.star.text.XTextRange;
48 import com.sun.star.text.XText;
49 import com.sun.star.rdf.*;
50 import lib.TestParameters;
51 
52 import org.junit.After;
53 import org.junit.AfterClass;
54 import org.junit.Before;
55 import org.junit.BeforeClass;
56 import org.junit.Test;
57 import org.openoffice.test.OfficeConnection;
58 import static org.junit.Assert.*;
59 
60 /**
61  * Test case for service com.sun.star.rdf.Repository
62  * Currently, this service is implemented in
63  * unoxml/source/rdf/librdf_repository.cxx
64  *
65  * @author mst
66  */
67 public class RDFRepositoryTest
68 {
69     XComponentContext xContext;
70     String tempDir;
71 
72     XDocumentRepository xRep;
73     XURI foo;
74     XURI bar;
75     XURI baz;
76     XURI uint;
77     XURI rdfslabel;
78     XURI manifest;
79     XURI uuid;
80     XURI base;
81     XBlankNode blank;
82     XLiteral lit;
83     XLiteral litlang;
84     XLiteral littype;
85     String rdfs = "http://www.w3.org/2000/01/rdf-schema#";
86 
87     /**
88      * The test parameters
89      */
90     private static TestParameters param = null;
91 
92 //    public String[] getTestMethodNames ()
93 //    {
94 //        return new String[] { "check", "checkSPARQL", "checkRDFa" };
95 //    }
96 
97     @Before public void before()
98     {
99         try {
100             XMultiServiceFactory xMSF = getMSF();
101             param = new TestParameters();
102             param.put("ServiceFactory", xMSF);
103 
104             assertNotNull("could not create MultiServiceFactory.", xMSF);
105             XPropertySet xPropertySet = UnoRuntime.queryInterface(XPropertySet.class, xMSF);
106             Object defaultCtx = xPropertySet.getPropertyValue("DefaultContext");
107             xContext = UnoRuntime.queryInterface(XComponentContext.class, defaultCtx);
108             assertNotNull("could not get component context.", xContext);
109 
110             tempDir = util.utils.getOfficeTemp/*Dir*/(xMSF);
111             System.out.println("tempdir: " + tempDir);
112 
113             foo = URI.create(xContext, "uri:foo");
114             assertNotNull("foo", foo);
115             bar = URI.create(xContext, "uri:bar");
116             assertNotNull("bar", bar);
117             baz = URI.create(xContext, "uri:baz");
118             assertNotNull("baz", baz);
119             uint = URI.create(xContext, "uri:int");
120             assertNotNull("uint", uint);
121             blank = BlankNode.create(xContext, "_:uno");
122             assertNotNull("blank", blank);
123             lit = Literal.create(xContext, "i am the literal");
124             assertNotNull("lit", lit);
125             litlang = Literal.createWithLanguage(xContext,
126                 "i am the literal", "en");
127             assertNotNull("litlang", litlang);
128             littype = Literal.createWithType(xContext, "42", uint);
129             assertNotNull("littype", littype);
130 
131             rdfslabel = URI.create(xContext, rdfs + "label");
132             assertNotNull("rdfslabel", rdfslabel);
133             manifest = URI.create(xContext, "manifest:manifest"); //FIXME
134             assertNotNull("manifest", manifest);
135             uuid = URI.create(xContext,
136                 "urn:uuid:224ab023-77b8-4396-a75a-8cecd85b81e3");
137             assertNotNull("uuid", uuid);
138             base = URI.create(xContext, "base-uri:"); //FIXME
139             assertNotNull("base", base);
140         } catch (Exception e) {
141             report(e);
142         }
143         //FIXME: ?
144 //            xRep = Repository.create(xContext);
145         System.out.println("Creating service Repository...");
146         xRep = UnoRuntime.queryInterface(XDocumentRepository.class, Repository.create(xContext));
147         assertNotNull("null", xRep);
148         System.out.println("...done");
149     }
150 
151     @After public void after()
152     {
153         xRep = null;
154     }
155 
156     @Test public void check()
157     {
158         try {
159             System.out.println("Checking that new repository is really empty...");
160             assertTrue("empty: graphs", 0 == xRep.getGraphNames().length);
161 
162             XEnumeration stmts;
163             stmts = xRep.getStatements(null, null, null);
164             assertTrue("empty: stmts", !stmts.hasMoreElements());
165 
166             System.out.println("...done");
167 
168             System.out.println("Checking graph creation...");
169 
170             XNamedGraph xFooGraph = xRep.createGraph(foo);
171             assertNotNull("foo graph", xFooGraph);
172 
173             try {
174                 xRep.createGraph(foo);
175                 fail("creating duplicate graph was allowed");
176             } catch (ElementExistException e) {
177                 // ignore
178             }
179 
180             try {
181                 xRep.createGraph(null);
182                 fail("invalid graph name was allowed");
183             } catch (IllegalArgumentException e) {
184                 // ignore
185             }
186 
187             XURI[] names = xRep.getGraphNames();
188             assertTrue("no foo graph in getGraphNames",
189                 1 == names.length && eq(names[0], foo));
190             assertNotNull("no foo graph", xRep.getGraph(foo));
191 
192             stmts = xFooGraph.getStatements(null, null, null);
193             assertTrue("stmts in foo graph", !stmts.hasMoreElements());
194 
195             XOutputStream xFooOut =
196                 new StreamSimulator(tempDir + "empty.rdf", false, param);
197             xRep.exportGraph(FileFormat.RDF_XML, xFooOut, foo, base);
198             xFooOut.closeOutput();
199 
200             XInputStream xFooIn =
201                 new StreamSimulator(tempDir + "empty.rdf", true, param);
202             xRep.importGraph(FileFormat.RDF_XML, xFooIn, bar, base);
203             assertNotNull("no bar graph", xRep.getGraph(bar));
204 
205             System.out.println("...done");
206 
207             System.out.println("Checking graph manipulation...");
208 
209             XEnumeration xFooEnum;
210 
211             Statement xFoo_FooBarBaz = new Statement(foo, bar, baz, foo);
212             xFooGraph.addStatement(foo, bar, baz);
213             xFooEnum = xFooGraph.getStatements(null, null, null);
214             assertTrue("addStatement(foo,bar,baz)",
215                 eq(xFooEnum, new Statement[] { xFoo_FooBarBaz }));
216 
217             Statement xFoo_FooBarBlank = new Statement(foo, bar, blank, foo);
218             xFooGraph.addStatement(foo, bar, blank);
219             xFooEnum = xFooGraph.getStatements(null, null, null);
220             assertTrue("addStatement(foo,bar,blank)",
221                 eq(xFooEnum,
222                     new Statement[] { xFoo_FooBarBaz, xFoo_FooBarBlank }));
223             xFooEnum = xRep.getStatements(null, null, null);
224             assertTrue("addStatement(foo,bar,blank) (global)",
225                 eq(xFooEnum,
226                     new Statement[] { xFoo_FooBarBaz, xFoo_FooBarBlank }));
227 
228             Statement xFoo_BazBarLit = new Statement(baz, bar, lit, foo);
229             xFooGraph.addStatement(baz, bar, lit);
230             xFooEnum = xFooGraph.getStatements(null, null, null);
231             assertTrue("addStatement(baz,bar,lit)",
232                 eq(xFooEnum, new Statement[] {
233                     xFoo_FooBarBaz, xFoo_FooBarBlank, xFoo_BazBarLit }));
234             xFooEnum = xFooGraph.getStatements(baz, bar, null);
235             assertTrue("addStatement(baz,bar,lit) (baz,bar)",
236                 eq(xFooEnum, new Statement[] { xFoo_BazBarLit }));
237 
238             Statement xFoo_BazBarLitlang =
239                 new Statement(baz, bar, litlang, foo);
240             xFooGraph.addStatement(baz, bar, litlang);
241             xFooEnum = xFooGraph.getStatements(null, null, null);
242             assertTrue("addStatement(baz,bar,litlang)",
243                 eq(xFooEnum, new Statement[] {
244                     xFoo_FooBarBaz, xFoo_FooBarBlank, xFoo_BazBarLit,
245                     xFoo_BazBarLitlang }));
246             xFooEnum = xFooGraph.getStatements(null, null, baz);
247             assertTrue("addStatement(baz,bar,litlang) (baz)",
248                 eq(xFooEnum, new Statement[] { xFoo_FooBarBaz }));
249 
250             Statement xFoo_BazBarLittype =
251                 new Statement(baz, bar, littype, foo);
252             xFooGraph.addStatement(baz, bar, littype);
253             xFooEnum = xFooGraph.getStatements(null, null, null);
254             assertTrue("addStatement(baz,bar,littype)",
255                 eq(xFooEnum, new Statement[] { xFoo_FooBarBaz, xFoo_FooBarBlank,
256                     xFoo_BazBarLit, xFoo_BazBarLitlang, xFoo_BazBarLittype }));
257 
258             xFooGraph.removeStatements(baz, bar, litlang);
259             xFooEnum = xFooGraph.getStatements(null, null, null);
260             assertTrue("removeStatement(baz,bar,litlang)",
261                 eq(xFooEnum, new Statement[] { xFoo_FooBarBaz, xFoo_FooBarBlank,
262                     xFoo_BazBarLit, xFoo_BazBarLittype }));
263 
264             xFooGraph.removeStatements(foo, bar, null);
265             xFooEnum = xFooGraph.getStatements(null, null, null);
266             assertTrue("removeStatement(foo,bar,null)",
267                 eq(xFooEnum, new Statement[] {
268                     xFoo_BazBarLit, xFoo_BazBarLittype }));
269 
270             xFooGraph.addStatement(foo, bar, baz);
271             xFooEnum = xFooGraph.getStatements(null, null, null);
272             assertTrue("addStatement(foo,bar,baz) (re-add)",
273                 eq(xFooEnum, new Statement[] { xFoo_FooBarBaz,
274                     xFoo_BazBarLit, xFoo_BazBarLittype }));
275 
276             xFooGraph.addStatement(foo, bar, baz);
277             xFooEnum = xFooGraph.getStatements(null, null, null);
278             assertTrue("addStatement(foo,bar,baz) (duplicate)",
279                 eq(xFooEnum, new Statement[] { xFoo_FooBarBaz,
280                     xFoo_BazBarLit, xFoo_BazBarLittype }));
281 
282             xFooGraph.addStatement(xFooGraph, bar, baz);
283             xFooEnum = xFooGraph.getStatements(null, null, null);
284             assertTrue("addStatement(foo,bar,baz) (triplicate, as graph)",
285                 eq(xFooEnum, new Statement[] { xFoo_FooBarBaz,
286                      xFoo_BazBarLit, xFoo_BazBarLittype }));
287 
288             System.out.println("...done");
289 
290             System.out.println("Checking graph import/export...");
291 
292             xFooOut = new StreamSimulator(tempDir + "foo.rdf", false, param);
293             xRep.exportGraph(FileFormat.RDF_XML, xFooOut, foo, base);
294             xFooOut.closeOutput();
295 
296             xFooIn = new StreamSimulator(tempDir + "foo.rdf", true, param);
297             try {
298                 xRep.importGraph(FileFormat.RDF_XML, xFooIn, bar, base);
299                 fail("importing existing graph did not fail");
300             } catch (ElementExistException e) {
301                 // ignore
302             }
303 
304             xFooIn = new StreamSimulator(tempDir + "foo.rdf", true, param);
305             xRep.importGraph(FileFormat.RDF_XML, xFooIn, baz, base);
306             XNamedGraph xBazGraph =  xRep.getGraph(baz);
307             assertNotNull("no baz graph", xBazGraph);
308 
309             Statement xBaz_FooBarBaz = new Statement(foo, bar, baz, baz);
310             Statement xBaz_BazBarLit = new Statement(baz, bar, lit, baz);
311             Statement xBaz_BazBarLittype =
312                 new Statement(baz, bar, littype, baz);
313             XEnumeration xBazEnum = xBazGraph.getStatements(null, null, null);
314             assertTrue("importing exported graph",
315                 eq(xBazEnum, new Statement[] {
316                      xBaz_FooBarBaz, xBaz_BazBarLit, xBaz_BazBarLittype }));
317 
318             System.out.println("...done");
319 
320             System.out.println("Checking graph deletion...");
321 
322             xFooGraph.clear();
323             xFooEnum = xFooGraph.getStatements(null, null, null);
324             assertTrue("clear", eq(xFooEnum, new Statement[] { }));
325 
326             xRep.destroyGraph(baz);
327             assertNull("baz graph zombie", xRep.getGraph(baz));
328 
329             try {
330                 xBazGraph.clear();
331                 fail("deleted graph not invalid (clear)");
332             } catch (NoSuchElementException e) {
333                 // ignore
334             }
335 
336             try {
337                 xBazGraph.addStatement(foo, foo, foo);
338                 fail("deleted graph not invalid (add)");
339             } catch (NoSuchElementException e) {
340                 // ignore
341             }
342 
343             try {
344                 xBazGraph.removeStatements(null, null, null);
345                 fail("deleted graph not invalid (remove)");
346             } catch (NoSuchElementException e) {
347                 // ignore
348             }
349 
350             try {
351                 xBazGraph.getStatements(null, null, null);
352                 fail("deleted graph not invalid (get)");
353             } catch (NoSuchElementException e) {
354                 // ignore
355             }
356 
357             System.out.println("...done");
358 
359         } catch (Exception e) {
360             report(e);
361         }
362     }
363 
364     @Test public void checkSPARQL()
365     {
366         try {
367 
368             System.out.println("Checking SPARQL queries...");
369 
370             XInputStream xIn = new StreamSimulator(TestDocument.getUrl("example.rdf"), true, param);
371                 // util.utils.getFullTestDocName("example.rdf"), true, param);
372             xRep.importGraph(FileFormat.RDF_XML, xIn, manifest, base);
373 
374             String query;
375             query = "SELECT ?p WHERE { ?p rdf:type pkg:Package . }";
376             XQuerySelectResult result = xRep.querySelect(mkNss() + query);
377             assertTrue("query: package-id\n" + query,
378                 eq(result, new String[] { "p" },
379                     new XNode[][] { { uuid } }));
380 
381             query = "SELECT ?part ?path FROM <" + manifest +
382                "> WHERE { ?pkg rdf:type pkg:Package . ?pkg pkg:hasPart ?part ."
383                + " ?part pkg:path ?path . ?part rdf:type odf:ContentFile. }";
384             result = xRep.querySelect(mkNss() + query);
385             assertTrue("query: contentfile",
386                 eq(result, new String[] { "part", "path" },
387                     new XNode[][] { { BlankNode.create(xContext, "whatever"),
388                             Literal.create(xContext, "content.xml") } }));
389 
390             query = "SELECT ?pkg ?path FROM <" + toS(manifest) +  "> WHERE { "
391                 + "?pkg rdf:type pkg:Package . ?pkg pkg:hasPart ?part . "
392                 + "?part pkg:path ?path . ?part rdf:type odf:ContentFile. }";
393             result = xRep.querySelect(mkNss() + query);
394             assertTrue("query: contentfile\n" + query,
395                 eq(result, new String[] { "pkg", "path" },
396                     new XNode[][] { { uuid ,
397                             Literal.create(xContext, "content.xml") } }));
398 
399             query = "SELECT ?part ?path FROM <" + toS(manifest) + "> WHERE { "
400                 + "?pkg rdf:type pkg:Package . ?pkg pkg:hasPart ?part . "
401                 + "?part pkg:path ?path . ?part rdf:type odf:StylesFile. }";
402             result = xRep.querySelect(mkNss() + query);
403             assertTrue("query: stylesfile\n" + query,
404                 eq(result, new String[] { "part", "path" },
405                     new XNode[][] { }));
406 
407             query = "SELECT ?part ?path FROM <" + toS(manifest) + "> WHERE { "
408                 + "?pkg rdf:type pkg:Package . ?pkg pkg:hasPart ?part . "
409                 + "?part pkg:path ?path . ?part rdf:type odf:MetadataFile. }";
410             result = xRep.querySelect(mkNss() + query);
411             assertTrue("query: metadatafile\n" + query,
412                 eq(result, new String[] { "part", "path" },
413                     new XNode[][] { {
414                         URI.create(xContext, "http://hospital-employee/doctor"),
415                         Literal.create(xContext,
416                             "meta/hospital/doctor.rdf") } }));
417 
418 //FIXME redland BUG
419             String uri = "uri:example-element-2";
420             query = "SELECT ?path ?idref FROM <" + toS(manifest) +  "> WHERE { "
421 //                + "<" + toS(uuid) + "> rdf:type pkg:Package ; "
422 //                                 + " pkg:hasPart ?part . "
423                 + "<" + toS(uuid) + "> pkg:hasPart ?part . "
424                 + "?part pkg:path ?path ; "
425                      + " rdf:type ?type ; "
426                      + " pkg:hasPart <" + uri + "> . "
427 //                + "<" + uri + "> rdf:type odf:Element ; "
428                 + "<" + uri + "> "
429                       + " pkg:idref ?idref . "
430                 + " FILTER (?type = odf:ContentFile || ?type = odf:StylesFile)"
431                 + " }";
432 //System.out.println(query);
433             result = xRep.querySelect(mkNss() + query);
434             assertTrue("query: example-element-2\n" + query,
435                 eq(result, new String[] { "path", "idref" },
436                     new XNode[][] { {
437                         Literal.create(xContext, "content.xml"),
438                         Literal.create(xContext, "ID_B") } }));
439 
440             // CONSTRUCT result triples have no graph!
441             Statement x_PkgFooLit = new Statement(uuid, foo, lit, null);
442             query = "CONSTRUCT { ?pkg <" + toS(foo) + "> \"" +
443                 lit.getStringValue() + "\" } FROM <" + toS(manifest) +
444                 "> WHERE { ?pkg rdf:type pkg:Package . } ";
445             XEnumeration xResultEnum = xRep.queryConstruct(mkNss() + query);
446             assertTrue("query: construct\n" + query,
447                 eq(xResultEnum, new Statement[] { x_PkgFooLit }));
448 
449             query = "ASK { ?pkg rdf:type pkg:Package . }";
450             boolean bResult = xRep.queryAsk(mkNss() + query);
451             assertTrue("query: ask\n" + query, bResult);
452 
453             System.out.println("...done");
454 
455         } catch (Exception e) {
456             report(e);
457         }
458     }
459 
460     @Test public void checkRDFa()
461     {
462         try {
463             System.out.println("Checking RDFa gunk...");
464 
465             String content = "behold, for i am the content.";
466             XTextRange xTR = new TestRange(content);
467             XMetadatable xM = (XMetadatable) xTR;
468 
469             Pair<Statement[], Boolean> result =
470                 xRep.getStatementRDFa((XMetadatable)xTR);
471             assertTrue("RDFa: get: not empty (initial)",
472                 0 == result.First.length);
473 
474             try {
475                 xRep.setStatementRDFa(foo, new XURI[] {}, xM, "", null);
476                 fail("RDFa: set: no predicate");
477             } catch (IllegalArgumentException e) {
478                 // ignore
479             }
480 
481             try {
482                 xRep.setStatementRDFa(foo, new XURI[] {bar}, null, "", null);
483                 fail("RDFa: set: null");
484             } catch (IllegalArgumentException e) {
485                 // ignore
486             }
487 
488             XLiteral trlit = Literal.create(xContext, content);
489             Statement x_FooBarTRLit = new Statement(foo, bar, trlit, null);
490             xRep.setStatementRDFa(foo, new XURI[] { bar }, xM, "", null);
491 
492             result = xRep.getStatementRDFa((XMetadatable)xTR);
493             assertTrue("RDFa: get: without content",
494                 !result.Second && (1 == result.First.length)
495                 && eq(result.First[0], x_FooBarTRLit));
496 
497             //FIXME: do this?
498             xTR.setString(lit.getStringValue());
499 /*
500             Statement xFooBarLit = new Statement(foo, bar, lit, null);
501             result = xRep.getStatementRDFa((XMetadatable)xTR);
502             assertTrue("RDFa: get: change",
503                 eq((Statement)result.First, xFooBarLit) && null == result.Second);
504 */
505 
506             Statement x_FooBarLittype = new Statement(foo, bar, littype, null);
507             xRep.setStatementRDFa(foo, new XURI[] { bar }, xM, "42", uint);
508 
509             result = xRep.getStatementRDFa((XMetadatable)xTR);
510             assertTrue("RDFa: get: with content",
511                 result.Second &&
512                 (1 == result.First.length) &&
513                 eq(result.First[0], x_FooBarLittype));
514 
515             //FIXME: do this?
516             xTR.setString(content);
517 /*
518             Statement xFooLabelTRLit = new Statement(foo, rdfslabel, trlit, null);
519             result = xRep.getStatementRDFa((XMetadatable)xTR);
520             assertTrue("RDFa: get: change (label)",
521                 eq((Statement)result.First, xFooBarLittype) &&
522                 eq((Statement)result.Second, xFooLabelTRLit));
523 */
524 
525             xRep.removeStatementRDFa((XMetadatable)xTR);
526 
527             result = xRep.getStatementRDFa((XMetadatable)xTR);
528             assertTrue("RDFa: get: not empty (removed)",
529                 0 == result.First.length);
530 
531             xRep.setStatementRDFa(foo, new XURI[] { foo, bar, baz }, xM,
532                 "", null);
533 
534             Statement x_FooFooTRLit = new Statement(foo, foo, trlit, null);
535             Statement x_FooBazTRLit = new Statement(foo, baz, trlit, null);
536             result = xRep.getStatementRDFa((XMetadatable) xTR);
537             assertTrue("RDFa: get: without content (multiple predicates, reinsert)",
538                 !result.Second &&
539                 eq(result.First, new Statement[] {
540                      x_FooFooTRLit, x_FooBarTRLit, x_FooBazTRLit }));
541 
542             xRep.removeStatementRDFa((XMetadatable)xTR);
543 
544             result = xRep.getStatementRDFa((XMetadatable) xTR);
545             assertTrue("RDFa: get: not empty (re-removed)",
546                 0 == result.First.length);
547 
548             System.out.println("...done");
549 
550         } catch (Exception e) {
551             report(e);
552         }
553     }
554 
555 // utilities -------------------------------------------------------------
556 
557     public void report2(Exception e)
558     {
559         if (e instanceof WrappedTargetException)
560         {
561             System.out.println("Cause:");
562             Exception cause = (Exception)
563                 (((WrappedTargetException)e).TargetException);
564             System.out.println(cause.toString());
565             report2(cause);
566         } else if (e instanceof WrappedTargetRuntimeException) {
567             System.out.println("Cause:");
568             Exception cause = (Exception)
569                 (((WrappedTargetRuntimeException)e).TargetException);
570             System.out.println(cause.toString());
571             report2(cause);
572         }
573     }
574 
575     public void report(Exception e) {
576         System.out.println("Exception occurred:");
577         e.printStackTrace();
578         report2(e);
579         fail();
580     }
581 
582     public static String toS(XNode n) {
583         if (null == n)
584         {
585             return "< null >";
586         }
587         return n.getStringValue();
588     }
589 
590     static boolean isBlank(XNode i_node)
591     {
592         XBlankNode blank = UnoRuntime.queryInterface(XBlankNode.class, i_node);
593         return blank != null;
594     }
595 
596 /*
597     static class Statement implements XStatement
598     {
599         XResource m_Subject;
600         XResource m_Predicate;
601         XNode m_Object;
602         XURI m_Graph;
603 
604         Statement(XResource i_Subject, XResource i_Predicate, XNode i_Object,
605             XURI i_Graph)
606         {
607             m_Subject = i_Subject;
608             m_Predicate = i_Predicate;
609             m_Object = i_Object;
610             m_Graph = i_Graph;
611         }
612 
613         public XResource getSubject() { return m_Subject; }
614         public XResource getPredicate() { return m_Predicate; }
615         public XNode getObject() { return m_Object; }
616         public XURI getGraph() { return m_Graph; }
617     }
618 */
619 
620     static Statement[] toSeq(XEnumeration i_Enum) throws Exception
621     {
622         java.util.Collection c = new java.util.Vector();
623         while (i_Enum.hasMoreElements()) {
624             Statement s = (Statement) i_Enum.nextElement();
625 //System.out.println("toSeq: " + s.getSubject().getStringValue() + " " + s.getPredicate().getStringValue() + " " + s.getObject().getStringValue() + ".");
626             c.add(s);
627         }
628 //        return (Statement[]) c.toArray();
629         // java sucks
630         Object[] arr = c.toArray();
631         Statement[] ret = new Statement[arr.length];
632         for (int i = 0; i < arr.length; ++i) {
633             ret[i] = (Statement) arr[i];
634         }
635         return ret;
636     }
637 
638     static XNode[][] toSeqs(XEnumeration i_Enum) throws Exception
639     {
640         java.util.Collection c = new java.util.Vector();
641         while (i_Enum.hasMoreElements()) {
642             XNode[] s = (XNode[]) i_Enum.nextElement();
643             c.add(s);
644         }
645 //        return (XNode[][]) c.toArray();
646         Object[] arr = c.toArray();
647         XNode[][] ret = new XNode[arr.length][];
648         for (int i = 0; i < arr.length; ++i) {
649             ret[i] = (XNode[]) arr[i];
650         }
651         return ret;
652     }
653 
654     static class BindingComp implements java.util.Comparator
655     {
656         public int compare(Object i_Left, Object i_Right)
657         {
658             XNode[] left = (XNode[]) i_Left;
659             XNode[] right = (XNode[]) i_Right;
660             if (left.length != right.length)
661             {
662                 throw new RuntimeException();
663             }
664             for (int i = 0; i < left.length; ++i) {
665                 int eq = (left[i].getStringValue().compareTo(
666                             right[i].getStringValue()));
667                 if (eq != 0) return eq;
668             }
669             return 0;
670         }
671     }
672 
673     static class StmtComp implements java.util.Comparator
674     {
675         public int compare(Object i_Left, Object i_Right)
676         {
677             int eq;
678             Statement left = (Statement) i_Left;
679             Statement right = (Statement) i_Right;
680             if ((eq = cmp(left.Graph,     right.Graph    )) != 0)
681             {
682                 return eq;
683             }
684             if ((eq = cmp(left.Subject,   right.Subject  )) != 0)
685             {
686                 return eq;
687             }
688             if ((eq = cmp(left.Predicate, right.Predicate)) != 0)
689             {
690                 return eq;
691             }
692             if ((eq = cmp(left.Object,    right.Object   )) != 0)
693             {
694                 return eq;
695             }
696             return 0;
697         }
698 
699         public int cmp(XNode i_Left, XNode i_Right)
700         {
701             if (isBlank(i_Left)) {
702                 return isBlank(i_Right) ? 0 : 1;
703             } else {
704                 if (isBlank(i_Right)) {
705                     return -1;
706                 } else {
707                     return toS(i_Left).compareTo(toS(i_Right));
708                 }
709             }
710         }
711     }
712 
713     static boolean eq(Statement i_Left, Statement i_Right)
714     {
715         XURI lG = i_Left.Graph;
716         XURI rG = i_Right.Graph;
717         if (!eq(lG, rG)) {
718             System.out.println("Graphs differ: " + toS(lG) + " != " + toS(rG));
719             return false;
720         }
721         if (!eq(i_Left.Subject, i_Right.Subject)) {
722             System.out.println("Subjects differ: " +
723                 i_Left.Subject.getStringValue() + " != " +
724                 i_Right.Subject.getStringValue());
725             return false;
726         }
727         if (!eq(i_Left.Predicate, i_Right.Predicate)) {
728             System.out.println("Predicates differ: " +
729                 i_Left.Predicate.getStringValue() + " != " +
730                 i_Right.Predicate.getStringValue());
731             return false;
732         }
733         if (!eq(i_Left.Object, i_Right.Object)) {
734             System.out.println("Objects differ: " +
735                 i_Left.Object.getStringValue() + " != " +
736                 i_Right.Object.getStringValue());
737             return false;
738         }
739         return true;
740     }
741 
742     static boolean eq(Statement[] i_Result, Statement[] i_Expected)
743     {
744         if (i_Result.length != i_Expected.length) {
745             System.out.println("eq: different lengths: " + i_Result.length + " " +
746                 i_Expected.length);
747             return false;
748         }
749         Statement[] expected = (Statement[])
750             java.util.Arrays.asList(i_Expected).toArray();
751         java.util.Arrays.sort(i_Result, new StmtComp());
752         java.util.Arrays.sort(expected, new StmtComp());
753         for (int i = 0; i < expected.length; ++i) {
754             if (!eq(i_Result[i], expected[i]))
755             {
756                 return false;
757             }
758         }
759         return true;
760     }
761 
762     static boolean eq(XEnumeration i_Enum, Statement[] i_Expected)
763         throws Exception
764     {
765         Statement[] current = toSeq(i_Enum);
766         return eq(current, i_Expected);
767     }
768 
769     static boolean eq(XNode i_Left, XNode i_Right)
770     {
771         if (i_Left == null) {
772             return (i_Right == null);
773         } else {
774             return (i_Right != null) &&
775                 (i_Left.getStringValue().equals(i_Right.getStringValue())
776                 // FIXME: hack: blank nodes considered equal
777                 || (isBlank(i_Left) && isBlank(i_Right)));
778         }
779     }
780 
781     static boolean eq(XQuerySelectResult i_Result,
782             String[] i_Vars, XNode[][] i_Bindings) throws Exception
783     {
784         String[] vars = (String[]) i_Result.getBindingNames();
785         XEnumeration iter = (XEnumeration) i_Result;
786         XNode[][] bindings = toSeqs(iter);
787         if (vars.length != i_Vars.length) {
788             System.out.println("var lengths differ");
789             return false;
790         }
791         if (bindings.length != i_Bindings.length) {
792             System.out.println("binding lengths differ: " + i_Bindings.length +
793                 " vs " + bindings.length );
794             return false;
795         }
796         java.util.Arrays.sort(bindings, new BindingComp());
797         java.util.Arrays.sort(i_Bindings, new BindingComp());
798         for (int i = 0; i < i_Bindings.length; ++i) {
799             if (i_Bindings[i].length != i_Vars.length) {
800                 System.out.println("TEST ERROR!");
801                 throw new Exception();
802             }
803             if (bindings[i].length != i_Vars.length) {
804                 System.out.println("binding length and var length differ");
805                 return false;
806             }
807             for (int j = 0; j < i_Vars.length; ++j) {
808                 if (!eq(bindings[i][j], i_Bindings[i][j])) {
809                     System.out.println("bindings differ: " +
810                         toS(bindings[i][j]) + " != " + toS(i_Bindings[i][j]));
811                     return false;
812                 }
813             }
814         }
815         for (int i = 0; i < i_Vars.length; ++i) {
816             if (!vars[i].equals(i_Vars[i])) {
817                 System.out.println("variable names differ: " +
818                     vars[i] + " != " + i_Vars[i]);
819                 return false;
820             }
821         }
822         return true;
823     }
824 
825     static String mkNamespace(String i_prefix, String i_namespace)
826     {
827         return "PREFIX " + i_prefix + ": <" + i_namespace + ">\n";
828     }
829 
830     static String mkNss()
831     {
832         String namespaces = mkNamespace("rdf",
833             "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
834         namespaces += mkNamespace("pkg",
835             "http://docs.oasis-open.org/opendocument/meta/package/common#");
836         namespaces += mkNamespace("odf",
837             "http://docs.oasis-open.org/opendocument/meta/package/odf#");
838         return namespaces;
839     }
840 
841     class TestRange implements XTextRange, XMetadatable, XServiceInfo
842     {
843         String m_Stream;
844         String m_XmlId;
845         String m_Text;
846         TestRange(String i_Str) { m_Text = i_Str; }
847 
848         public String getStringValue() { return ""; }
849         public String getNamespace() { return ""; }
850         public String getLocalName() { return ""; }
851 
852         public StringPair getMetadataReference()
853             { return new StringPair(m_Stream, m_XmlId); }
854         public void setMetadataReference(StringPair i_Ref)
855             throws IllegalArgumentException
856             { m_Stream = i_Ref.First; m_XmlId = i_Ref.Second; }
857         public void ensureMetadataReference()
858             { m_Stream = "content.xml"; m_XmlId = "42"; }
859 
860         public String getImplementationName() { return null; }
861         public String[] getSupportedServiceNames() { return null; }
862         public boolean supportsService(String i_Svc)
863             { return i_Svc.equals("com.sun.star.text.Paragraph"); }
864 
865         public XText getText() { return null; }
866         public XTextRange getStart() { return null; }
867         public XTextRange getEnd() { return null; }
868         public String getString() { return m_Text; }
869         public void setString(String i_Str) { m_Text = i_Str; }
870     }
871 
872         private XMultiServiceFactory getMSF()
873     {
874         final XMultiServiceFactory xMSF1 = UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager());
875         return xMSF1;
876     }
877 
878     // setup and close connections
879     @BeforeClass public static void setUpConnection() throws Exception {
880         System.out.println("setUpConnection()");
881         connection.setUp();
882     }
883 
884     @AfterClass public static void tearDownConnection()
885         throws InterruptedException, com.sun.star.uno.Exception
886     {
887         System.out.println("tearDownConnection()");
888         connection.tearDown();
889     }
890 
891     private static final OfficeConnection connection = new OfficeConnection();
892 }
893 
894