1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.rdf.api;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertNotNull;
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assert.fail;
25
26 import java.util.ArrayList;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Locale;
31 import java.util.Map;
32 import java.util.Optional;
33 import java.util.concurrent.ConcurrentHashMap;
34 import java.util.stream.Stream;
35
36 import org.junit.Assume;
37 import org.junit.Before;
38 import org.junit.Test;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public abstract class AbstractGraphTest {
55
56 protected RDF factory;
57 protected Graph graph;
58 protected IRI alice;
59 protected IRI bob;
60 protected IRI name;
61 protected IRI knows;
62 protected IRI member;
63 protected BlankNode bnode1;
64 protected BlankNode bnode2;
65 protected Literal aliceName;
66 protected Literal bobName;
67 protected Literal secretClubName;
68 protected Literal companyName;
69 protected Triple bobNameTriple;
70
71
72
73
74
75
76
77
78 protected abstract RDF createFactory();
79
80 @Before
81 public void createGraphAndAdd() {
82 factory = createFactory();
83 graph = factory.createGraph();
84 assertEquals(0, graph.size());
85
86 alice = factory.createIRI("http://example.com/alice");
87 bob = factory.createIRI("http://example.com/bob");
88 name = factory.createIRI("http://xmlns.com/foaf/0.1/name");
89 knows = factory.createIRI("http://xmlns.com/foaf/0.1/knows");
90 member = factory.createIRI("http://xmlns.com/foaf/0.1/member");
91 try {
92 bnode1 = factory.createBlankNode("org1");
93 bnode2 = factory.createBlankNode("org2");
94 } catch (final UnsupportedOperationException ex) {
95
96 }
97
98 try {
99 secretClubName = factory.createLiteral("The Secret Club");
100 companyName = factory.createLiteral("A company");
101 aliceName = factory.createLiteral("Alice");
102 bobName = factory.createLiteral("Bob", "en-US");
103 } catch (final UnsupportedOperationException ex) {
104
105 }
106
107 if (aliceName != null) {
108 graph.add(alice, name, aliceName);
109 }
110 graph.add(alice, knows, bob);
111
112 if (bnode1 != null) {
113 graph.add(alice, member, bnode1);
114 }
115
116 if (bobName != null) {
117 try {
118 bobNameTriple = factory.createTriple(bob, name, bobName);
119 } catch (final UnsupportedOperationException ex) {
120
121 }
122 if (bobNameTriple != null) {
123 graph.add(bobNameTriple);
124 }
125 }
126 if (bnode1 != null) {
127 graph.add(factory.createTriple(bob, member, bnode1));
128 graph.add(factory.createTriple(bob, member, bnode2));
129 if (secretClubName != null) {
130 graph.add(bnode1, name, secretClubName);
131 graph.add(bnode2, name, companyName);
132 }
133 }
134 }
135
136 @Test
137 public void size() throws Exception {
138 assertTrue(graph.size() > 0);
139 Assume.assumeNotNull(bnode1, bnode2, aliceName, bobName, secretClubName, companyName, bobNameTriple);
140
141 assertEquals(8, graph.size());
142 }
143
144 @Test
145 public void iterate() throws Exception {
146
147 Assume.assumeTrue(graph.size() > 0);
148
149 final List<Triple> triples = new ArrayList<>();
150 for (final Triple t : graph.iterate()) {
151 triples.add(t);
152 }
153 assertEquals(graph.size(), triples.size());
154 if (bobNameTriple != null) {
155 assertTrue(triples.contains(bobNameTriple));
156 }
157
158
159 final Iterable<Triple> iterate = graph.iterate();
160 final Iterator<Triple> it = iterate.iterator();
161
162 assertTrue(it.hasNext());
163 it.next();
164 closeIterable(iterate);
165
166
167
168 long count = 0;
169 final Iterable<Triple> iterable = graph.iterate();
170 for (@SuppressWarnings("unused") final
171 Triple t : iterable) {
172 count++;
173 }
174 assertEquals(graph.size(), count);
175 }
176
177
178
179
180 private void closeIterable(final Iterable<Triple> iterate) throws Exception {
181 if (iterate instanceof AutoCloseable) {
182 ((AutoCloseable) iterate).close();
183 }
184 }
185
186 @Test
187 public void iterateFilter() throws Exception {
188 final List<RDFTerm> friends = new ArrayList<>();
189 final IRI alice = factory.createIRI("http://example.com/alice");
190 final IRI knows = factory.createIRI("http://xmlns.com/foaf/0.1/knows");
191 for (final Triple t : graph.iterate(alice, knows, null)) {
192 friends.add(t.getObject());
193 }
194 assertEquals(1, friends.size());
195 assertEquals(bob, friends.get(0));
196
197
198 final Iterable<Triple> iterate = graph.iterate(bob, knows, alice);
199 for (final Triple unexpected : iterate) {
200 fail("Unexpected triple " + unexpected);
201 }
202
203 }
204
205 @Test
206 public void contains() throws Exception {
207 assertFalse(graph.contains(bob, knows, alice));
208
209 assertTrue(graph.contains(alice, knows, bob));
210
211 try (Stream<? extends Triple> stream = graph.stream()) {
212 final Optional<? extends Triple> first = stream.skip(4).findFirst();
213 Assume.assumeTrue(first.isPresent());
214 final Triple existingTriple = first.get();
215 assertTrue(graph.contains(existingTriple));
216 }
217
218 final Triple nonExistingTriple = factory.createTriple(bob, knows, alice);
219 assertFalse(graph.contains(nonExistingTriple));
220
221 Triple triple = null;
222 try {
223 triple = factory.createTriple(alice, knows, bob);
224 } catch (final UnsupportedOperationException ex) {
225 }
226 if (triple != null) {
227
228
229 }
230 }
231
232 @Test
233 public void remove() throws Exception {
234 final long fullSize = graph.size();
235 graph.remove(alice, knows, bob);
236 final long shrunkSize = graph.size();
237 assertEquals(1, fullSize - shrunkSize);
238
239 graph.remove(alice, knows, bob);
240 assertEquals(shrunkSize, graph.size());
241
242 graph.add(alice, knows, bob);
243 graph.add(alice, knows, bob);
244 graph.add(alice, knows, bob);
245
246
247 assertTrue(graph.size() > shrunkSize);
248
249
250 graph.remove(alice, knows, bob);
251 assertEquals(shrunkSize, graph.size());
252
253 Triple otherTriple;
254 try (Stream<? extends Triple> stream = graph.stream()) {
255 final Optional<? extends Triple> anyTriple = stream.findAny();
256 Assume.assumeTrue(anyTriple.isPresent());
257 otherTriple = anyTriple.get();
258 }
259
260 graph.remove(otherTriple);
261 assertEquals(shrunkSize - 1, graph.size());
262 graph.remove(otherTriple);
263 assertEquals(shrunkSize - 1, graph.size());
264
265
266 graph.add(otherTriple);
267
268
269 assertTrue(graph.size() >= shrunkSize);
270 }
271
272 @Test
273 public void clear() throws Exception {
274 graph.clear();
275 assertFalse(graph.contains(alice, knows, bob));
276 assertEquals(0, graph.size());
277 graph.clear();
278 assertEquals(0, graph.size());
279 }
280
281 @Test
282 public void getTriples() throws Exception {
283 long tripleCount;
284 try (Stream<? extends Triple> stream = graph.stream()) {
285 tripleCount = stream.count();
286 }
287 assertTrue(tripleCount > 0);
288
289 try (Stream<? extends Triple> stream = graph.stream()) {
290 assertTrue(stream.allMatch(t -> graph.contains(t)));
291 }
292
293
294 Assume.assumeNotNull(bnode1, bnode2, aliceName, bobName, secretClubName, companyName, bobNameTriple);
295 assertEquals(8, tripleCount);
296 }
297
298 @Test
299 public void getTriplesQuery() throws Exception {
300
301 try (Stream<? extends Triple> stream = graph.stream(alice, null, null)) {
302 final long aliceCount = stream.count();
303 assertTrue(aliceCount > 0);
304 Assume.assumeNotNull(aliceName);
305 assertEquals(3, aliceCount);
306 }
307
308 Assume.assumeNotNull(bnode1, bnode2, bobName, companyName, secretClubName);
309 try (Stream<? extends Triple> stream = graph.stream(null, name, null)) {
310 assertEquals(4, stream.count());
311 }
312 Assume.assumeNotNull(bnode1);
313 try (Stream<? extends Triple> stream = graph.stream(null, member, null)) {
314 assertEquals(3, stream.count());
315 }
316 }
317
318 @Test
319 public void addBlankNodesFromMultipleGraphs() throws Exception {
320
321
322
323 try (final Graph g1 = createGraph1(); final Graph g2 = createGraph2(); final Graph g3 = factory.createGraph()) {
324 addAllTriples(g1, g3);
325 addAllTriples(g2, g3);
326
327
328
329
330
331
332 final Map<String, BlankNodeOrIRI> whoIsWho = new ConcurrentHashMap<>();
333
334
335
336
337
338 final IRI name = factory.createIRI("http://xmlns.com/foaf/0.1/name");
339 try (Stream<? extends Triple> stream = g3.stream(null, name, null)) {
340 stream.parallel().forEach(t -> whoIsWho.put(t.getObject().ntriplesString(), t.getSubject()));
341 }
342
343 assertEquals(4, whoIsWho.size());
344
345 assertEquals(4, new HashSet<>(whoIsWho.values()).size());
346
347 final BlankNodeOrIRI b1Alice = whoIsWho.get("\"Alice\"");
348 assertNotNull(b1Alice);
349 final BlankNodeOrIRI b2Bob = whoIsWho.get("\"Bob\"");
350 assertNotNull(b2Bob);
351 final BlankNodeOrIRI b1Charlie = whoIsWho.get("\"Charlie\"");
352 assertNotNull(b1Charlie);
353 final BlankNodeOrIRI b2Dave = whoIsWho.get("\"Dave\"");
354 assertNotNull(b2Dave);
355
356
357 notEquals(b1Alice, b2Bob);
358 notEquals(b1Alice, b1Charlie);
359 notEquals(b1Alice, b2Dave);
360 notEquals(b2Bob, b1Charlie);
361 notEquals(b2Bob, b2Dave);
362 notEquals(b1Charlie, b2Dave);
363
364
365
366 final IRI hasChild = factory.createIRI("http://example.com/hasChild");
367 assertTrue(g3.contains(b1Alice, hasChild, b2Bob));
368 assertTrue(g3.contains(b2Dave, hasChild, b1Charlie));
369
370 assertFalse(g3.contains(b1Alice, hasChild, b1Alice));
371 assertFalse(g3.contains(b1Alice, hasChild, b1Charlie));
372 assertFalse(g3.contains(b1Alice, hasChild, b2Dave));
373
374 assertFalse(g3.contains(b2Dave, hasChild, b1Alice));
375 assertFalse(g3.contains(b2Dave, hasChild, b1Alice));
376
377
378 assertFalse(g3.contains(b2Bob, hasChild, null));
379 assertFalse(g3.contains(b1Charlie, hasChild, null));
380 } catch (final UnsupportedOperationException ex) {
381 Assume.assumeNoException(ex);
382 }
383 }
384
385 @Test
386 public void containsLanguageTagsCaseInsensitive() throws Exception {
387
388
389 final Literal lower = factory.createLiteral("Hello", "en-gb");
390 final Literal upper = factory.createLiteral("Hello", "EN-GB");
391 final Literal mixed = factory.createLiteral("Hello", "en-GB");
392
393 final IRI example1 = factory.createIRI("http://example.com/s1");
394 final IRI greeting = factory.createIRI("http://example.com/greeting");
395
396 try (final Graph graph = factory.createGraph()) {
397 graph.add(example1, greeting, upper);
398
399
400 assertTrue(graph.contains(factory.createTriple(example1, greeting, upper)));
401 assertTrue(graph.contains(factory.createTriple(example1, greeting, lower)));
402 assertTrue(graph.contains(factory.createTriple(example1, greeting, mixed)));
403
404
405 assertTrue(graph.contains(null, null, upper));
406 assertTrue(graph.contains(null, null, lower));
407 assertTrue(graph.contains(null, null, mixed));
408 }
409 }
410
411 @Test
412 public void containsLanguageTagsCaseInsensitiveTurkish() throws Exception {
413
414
415
416
417
418
419 final Locale defaultLocale = Locale.getDefault();
420 try (final Graph g = factory.createGraph()) {
421 Locale.setDefault(Locale.ROOT);
422 final Literal lowerROOT = factory.createLiteral("moi", "fi");
423 final Literal upperROOT = factory.createLiteral("moi", "FI");
424 final Literal mixedROOT = factory.createLiteral("moi", "fI");
425 final IRI exampleROOT = factory.createIRI("http://example.com/s1");
426 final IRI greeting = factory.createIRI("http://example.com/greeting");
427 g.add(exampleROOT, greeting, mixedROOT);
428
429 final Locale turkish = Locale.forLanguageTag("TR");
430 Locale.setDefault(turkish);
431
432
433
434 Assume.assumeFalse("FI".toLowerCase().equals("fi"));
435
436
437
438 final Literal lower = factory.createLiteral("moi", "fi");
439 final Literal upper = factory.createLiteral("moi", "FI");
440 final Literal mixed = factory.createLiteral("moi", "fI");
441
442 final IRI exampleTR = factory.createIRI("http://example.com/s2");
443 g.add(exampleTR, greeting, upper);
444 assertTrue(g.contains(factory.createTriple(exampleTR, greeting, upper)));
445 assertTrue(g.contains(factory.createTriple(exampleTR, greeting, upperROOT)));
446 assertTrue(g.contains(factory.createTriple(exampleTR, greeting, lower)));
447 assertTrue(g.contains(factory.createTriple(exampleTR, greeting, lowerROOT)));
448 assertTrue(g.contains(factory.createTriple(exampleTR, greeting, mixed)));
449 assertTrue(g.contains(factory.createTriple(exampleTR, greeting, mixedROOT)));
450 assertTrue(g.contains(exampleTR, null, upper));
451 assertTrue(g.contains(exampleTR, null, upperROOT));
452 assertTrue(g.contains(exampleTR, null, lower));
453 assertTrue(g.contains(exampleTR, null, lowerROOT));
454 assertTrue(g.contains(exampleTR, null, mixed));
455 assertTrue(g.contains(exampleTR, null, mixedROOT));
456
457
458 assertTrue(g.contains(factory.createTriple(exampleROOT, greeting, upper)));
459 assertTrue(g.contains(factory.createTriple(exampleROOT, greeting, lower)));
460 assertTrue(g.contains(factory.createTriple(exampleROOT, greeting, mixed)));
461 assertTrue(g.contains(exampleROOT, null, upper));
462 assertTrue(g.contains(exampleROOT, null, lower));
463 assertTrue(g.contains(exampleROOT, null, mixed));
464 } finally {
465 Locale.setDefault(defaultLocale);
466 }
467 }
468
469
470 @Test
471 public void removeLanguageTagsCaseInsensitive() throws Exception {
472
473
474 final Literal lower = factory.createLiteral("Hello", "en-gb");
475 final Literal upper = factory.createLiteral("Hello", "EN-GB");
476 final Literal mixed = factory.createLiteral("Hello", "en-GB");
477
478 final IRI example1 = factory.createIRI("http://example.com/s1");
479 final IRI greeting = factory.createIRI("http://example.com/greeting");
480
481 try (final Graph graph = factory.createGraph()) {
482 graph.add(example1, greeting, upper);
483
484
485 graph.remove(example1, null, mixed);
486 assertFalse(graph.contains(null, greeting, null));
487
488 graph.add(example1, greeting, lower);
489 graph.remove(example1, null, upper);
490
491
492 graph.add(factory.createTriple(example1, greeting, mixed));
493 graph.remove(factory.createTriple(example1, greeting, upper));
494 assertFalse(graph.contains(null, greeting, null));
495 }
496 }
497
498 private static Optional<? extends Triple> closableFindAny(final Stream<? extends Triple> stream) {
499 try (Stream<? extends Triple> s = stream) {
500 return s.findAny();
501 }
502 }
503
504 @Test
505 public void streamLanguageTagsCaseInsensitive() throws Exception {
506
507
508 final Literal lower = factory.createLiteral("Hello", "en-gb");
509 final Literal upper = factory.createLiteral("Hello", "EN-GB");
510 final Literal mixed = factory.createLiteral("Hello", "en-GB");
511
512 final IRI example1 = factory.createIRI("http://example.com/s1");
513 final IRI greeting = factory.createIRI("http://example.com/greeting");
514
515 try (final Graph graph = factory.createGraph()) {
516 graph.add(example1, greeting, upper);
517
518
519 assertTrue(closableFindAny(graph.stream(null, null, upper)).isPresent());
520 assertTrue(closableFindAny(graph.stream(null, null, lower)).isPresent());
521 assertTrue(closableFindAny(graph.stream(null, null, mixed)).isPresent());
522
523
524 final Triple t = closableFindAny(graph.stream(null, null, lower)).get();
525 assertEquals(t, factory.createTriple(example1, greeting, mixed));
526 }
527 }
528
529 private void notEquals(final BlankNodeOrIRI node1, final BlankNodeOrIRI node2) {
530 assertFalse(node1.equals(node2));
531
532
533 assertFalse(node1.ntriplesString().equals(node2.ntriplesString()));
534 }
535
536
537
538
539
540
541
542
543
544
545
546
547 private void addAllTriples(final Graph source, final Graph target) {
548
549
550
551
552
553 try (Stream<? extends Triple> stream = source.stream()) {
554 stream.unordered().sequential().forEach(t -> target.add(t));
555 }
556 }
557
558
559
560
561
562 private Graph createGraph1() {
563 final RDF factory1 = createFactory();
564
565 final IRI name = factory1.createIRI("http://xmlns.com/foaf/0.1/name");
566 final Graph g1 = factory1.createGraph();
567 final BlankNode b1 = createOwnBlankNode("b1", "0240eaaa-d33e-4fc0-a4f1-169d6ced3680");
568 g1.add(b1, name, factory1.createLiteral("Alice"));
569
570 final BlankNode b2 = createOwnBlankNode("b2", "9de7db45-0ce7-4b0f-a1ce-c9680ffcfd9f");
571 g1.add(b2, name, factory1.createLiteral("Bob"));
572
573 final IRI hasChild = factory1.createIRI("http://example.com/hasChild");
574 g1.add(b1, hasChild, b2);
575
576 return g1;
577 }
578
579
580
581
582
583
584
585
586
587 private BlankNode createOwnBlankNode(final String name, final String uuid) {
588 return new BlankNode() {
589 @Override
590 public String ntriplesString() {
591 return "_: " + name;
592 }
593
594 @Override
595 public String uniqueReference() {
596 return uuid;
597 }
598
599 @Override
600 public int hashCode() {
601 return uuid.hashCode();
602 }
603
604 @Override
605 public boolean equals(final Object obj) {
606 if (!(obj instanceof BlankNode)) {
607 return false;
608 }
609 final BlankNode other = (BlankNode) obj;
610 return uuid.equals(other.uniqueReference());
611 }
612 };
613 }
614
615 private Graph createGraph2() {
616 final RDF factory2 = createFactory();
617 final IRI name = factory2.createIRI("http://xmlns.com/foaf/0.1/name");
618
619 final Graph g2 = factory2.createGraph();
620
621 final BlankNode b1 = createOwnBlankNode("b1", "bc8d3e45-a08f-421d-85b3-c25b373abf87");
622 g2.add(b1, name, factory2.createLiteral("Charlie"));
623
624 final BlankNode b2 = createOwnBlankNode("b2", "2209097a-5078-4b03-801a-6a2d2f50d739");
625 g2.add(b2, name, factory2.createLiteral("Dave"));
626
627 final IRI hasChild = factory2.createIRI("http://example.com/hasChild");
628
629 g2.add(b2, hasChild, b1);
630 return g2;
631 }
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650 @Test
651 public void whyJavaStreamsMightNotTakeOverFromSparql() throws Exception {
652 Assume.assumeNotNull(bnode1, bnode2, secretClubName);
653
654 try (Stream<? extends Triple> stream = graph.stream(null, knows, null)) {
655 assertEquals("\"The Secret Club\"",
656
657 stream.filter(t -> !graph.contains((BlankNodeOrIRI) t.getObject(), knows, t.getSubject()))
658 .map(knowsTriple -> {
659 try (Stream<? extends Triple> memberOf = graph
660
661
662 .stream((BlankNodeOrIRI) knowsTriple.getObject(), member, null)) {
663 return memberOf
664
665
666 .filter(memberTriple -> graph.contains(knowsTriple.getSubject(), member,
667
668 memberTriple.getObject()))
669 .findFirst().get().getObject();
670 }
671 })
672
673 .map(org -> {
674 try (Stream<? extends Triple> orgName = graph.stream((BlankNodeOrIRI) org, name,
675 null)) {
676 return orgName.findFirst().get().getObject().ntriplesString();
677 }
678 }).findFirst().get());
679 }
680 }
681 }