KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > graph > query > test > AbstractTestQuery


1   /*
2   (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
3   [See end of file]
4   $Id: AbstractTestQuery.java,v 1.35 2005/02/21 11:52:31 andy_seaborne Exp $
5 */

6
7 package com.hp.hpl.jena.graph.query.test;
8
9 import com.hp.hpl.jena.graph.*;
10 import com.hp.hpl.jena.graph.query.*;
11 import com.hp.hpl.jena.shared.JenaException;
12 import com.hp.hpl.jena.shared.QueryStageException;
13 import com.hp.hpl.jena.util.CollectionFactory;
14 import com.hp.hpl.jena.util.iterator.*;
15 import com.hp.hpl.jena.graph.impl.*;
16
17 import java.util.*;
18 import junit.framework.*;
19
20 /**
21     Abstract tests for graph query, parameterised on getGraph().
22     @author kers
23 */

24 public abstract class AbstractTestQuery extends QueryTestBase
25     {
26     public AbstractTestQuery(String JavaDoc name)
27         { super(name); }
28
29     public abstract Graph getGraph();
30
31     protected Query Q;
32     protected Node O = node( "?O" );
33     protected Graph empty;
34     protected Graph single;
35     
36     protected final Node [] none = new Node[] {};
37     
38     protected final Node [] justX = new Node [] {Query.X};
39     
40     public static TestSuite suite()
41         { return new TestSuite( QueryTest.class ); }
42         
43     public Graph getGraphWith( String JavaDoc facts )
44         { return graphAdd( getGraph(), facts ); }
45         
46     public void setUp()
47         {
48         Q = new Query();
49         empty = getGraphWith( "" );
50         single = getGraphWith( "spindizzies drive cities" );
51         }
52
53     private void testTreeQuery( String JavaDoc title, String JavaDoc content, String JavaDoc pattern, String JavaDoc correct )
54         {
55         Graph gc = getGraphWith( content ), gp = getGraphWith( pattern );
56         Graph answer = gc.queryHandler().prepareTree( gp ).executeTree();
57         if (title.equals( "" )) title = "checking {" + content + "} against {" + pattern + "} should give {" + correct + "}" + " not " + answer;
58         assertIsomorphic( title, getGraphWith( correct ), answer );
59         }
60         
61     private void testTreeQuery( String JavaDoc content, String JavaDoc pattern, String JavaDoc answer )
62         {
63         testTreeQuery( "checking", content, pattern, answer );
64         }
65         
66     private static final String JavaDoc [][] tests =
67         {
68             { "", "pigs might fly", "", "" },
69             { "", "", "pigs might fly", "" },
70             { "", "a pings b; b pings c", "a pings _x; _x pings c", "a pings b; b pings c" },
71             { "", "a pings b; b pings c; a pings x; x pings c", "a pings _x; _x pings c", "a pings b; b pings c; a pings x; x pings c" }
72         };
73         
74     public void testManyThings()
75         {
76         for (int i = 0; i < tests.length; i += 1)
77             testTreeQuery( tests[i][0], tests[i][1], tests[i][2], tests[i][3] );
78         }
79         
80     public void testAtomicTreeQuery()
81         {
82         testTreeQuery( "pigs might fly; birds will joke; cats must watch", "birds will joke", "birds will joke" );
83         }
84         
85     public void testCompositeTreeQuery()
86         {
87         testTreeQuery
88             ( "pigs might fly; birds will joke; cats must watch", "birds will joke; pigs might fly", "pigs might fly; birds will joke" );
89         }
90         
91     public void testChainedTreeQuery()
92         {
93         testTreeQuery( "a pings b; b pings c; c pings d", "a pings b; b pings c", "a pings b; b pings c" );
94         }
95         
96     public void testEmptyIterator()
97         {
98         Graph empty = getGraph();
99         Query q = new Query().addMatch( X, Y, Z );
100         BindingQueryPlan bqp = empty.queryHandler().prepareBindings( q, justX );
101         try
102             {
103             bqp.executeBindings().next();
104             fail( "there are no bindings; next() should fail" );
105             }
106         catch (NoSuchElementException e)
107             { pass(); }
108         }
109         
110     public void testBinding1( )
111         {
112         Graph single = getGraphWith( "rice grows quickly" );
113         Query q = new Query();
114         Node V1 = node( "?v1" ), V3 = node( "?v3" );
115         BindingQueryPlan qp = single.queryHandler().prepareBindings( q.addMatch( V1, node("grows"), V3 ), new Node[] {V1, V3} );
116         Domain binding = (Domain) qp.executeBindings().next();
117         assertEquals( "binding subject to rice", binding.get(0), node("rice") );
118         assertEquals( "binding object to quickly", binding.get(1), node("quickly") );
119         }
120
121     public void testBinding2() {
122         Graph several = getGraphWith("rice grows quickly; time isan illusion");
123         String JavaDoc[][] answers = { { "time", "isan", "illusion" }, {
124                 "rice", "grows", "quickly" }
125         };
126         boolean[] found = { false, false };
127         Query q = new Query();
128         Node V1 = node("?v1"), V2 = node("?v2"), V3 = node("?v3");
129         BindingQueryPlan qp =
130             several.queryHandler().prepareBindings(
131                 q.addMatch(V1, V2, V3),
132                 new Node[] { V1, V2, V3 });
133         Iterator bindings = qp.executeBindings();
134         for (int i = 0; i < answers.length; i += 1) {
135             if (bindings.hasNext() == false)
136                 fail("wanted some more results");
137             Domain bound = (Domain) bindings.next();
138             for (int k = 0; k < answers.length; k++) {
139                 if (found[k])
140                     continue;
141                 boolean match = true;
142                 for (int j = 0; j < 3; j += 1) {
143                     if (!bound.get(j).equals(node(answers[k][j]))) {
144                         match = false;
145                         break;
146                     }
147                 }
148                 if (match) {
149                     found[k] = true;
150                     break;
151                 }
152             }
153         }
154         for (int k = 0; k < answers.length; k++) {
155             if (!found[k])
156                 assertTrue("binding failure", false);
157         }
158         assertFalse("iterator should be empty", bindings.hasNext());
159     }
160
161
162     public void testMultiplePatterns()
163         {
164         Graph bookish = getGraphWith( "ben wrote Clayface; Starfish ingenre SF; Clayface ingenre Geology; bill wrote Starfish" );
165         Query q = new Query();
166         Node A = node( "?A" );
167         q.addMatch( X, node("wrote"), A ).addMatch( A, node("ingenre"), node("SF") );
168         BindingQueryPlan qp = bookish.queryHandler().prepareBindings( q, justX );
169         Iterator bindings = qp.executeBindings();
170         if (bindings.hasNext())
171             {
172             Domain it = (Domain) bindings.next();
173             if (it.size() > 0)
174                 {
175                 if (it.get(0).equals( node("bill") ))
176                     {
177                     if (bindings.hasNext())
178                         System.out.println( "! failed: more than one multiple pattern answer: " + bindings.next() );
179                     }
180                 else
181                     System.out.println( "! failed: multiple pattern answer should be 'bill'" );
182                 }
183             else
184                 System.out.println( "! failed: multiple pattern answer should have one element" );
185             }
186         else
187             System.out.println( "! failed: multiple pattern query should have an answer" );
188         }
189     
190     /**
191         Utility. Run the query <code>q</code> over the graph <code>g</code>
192         requesting the output variables <code>nodes</code>.
193      */

194     protected ExtendedIterator eb( Graph g, Query q, Node [] nodes )
195         { return g.queryHandler().prepareBindings( q, nodes ).executeBindings(); }
196     
197     protected List ebList( Graph g, Query q, Node [] nodes )
198         { return iteratorToList( eb( g, q, nodes ) ); }
199     
200     protected Set ebSet( Graph g, Query q, Node [] nodes )
201         { return iteratorToSet( eb( g, q, nodes ) ); }
202         
203     public void testNodeVariablesA()
204         {
205         Graph mine = getGraphWith( "storms hit England" );
206         Node spoo = node( "?spoo" );
207         Q.addMatch( spoo, node("hit"), node("England") );
208         ClosableIterator it = eb( mine, Q, new Node[] {spoo} );
209         assertTrue( "tnv: it has a solution", it.hasNext() );
210         assertEquals( "", node("storms"), ((List) it.next()).get(0) );
211         assertFalse( "tnv: just the one solution", it.hasNext() );
212         }
213    
214     public void testNodeVariablesB()
215         {
216         Graph mine = getGraphWith( "storms hit England" );
217         Node spoo = node( "?spoo" ), flarn = node( "?flarn" );
218         Q.addMatch( spoo, node("hit"), flarn );
219         ClosableIterator it = eb( mine, Q, new Node[] {flarn, spoo} );
220         assertTrue( "tnv: it has a solution", it.hasNext() );
221         List answer = (List) it.next();
222         assertEquals( "tnvB", node("storms"), answer.get(1) );
223         assertEquals( "tnvB", node("England"), answer.get(0) );
224         assertFalse( "tnv: just the one solution", it.hasNext() );
225         }
226
227     public void testBindingQuery()
228         {
229         Graph empty = getGraphWith( "" );
230         Graph base = getGraphWith( "pigs might fly; cats chase mice; dogs chase cars; cats might purr" );
231     /* */
232         Query any = new Query().addMatch( Query.ANY, Query.ANY, Query.ANY );
233         assertFalse( "empty graph, no bindings", eb( empty, any, none ).hasNext() );
234         assertTrue( "full graph, > 0 bindings", eb( base, new Query(), none ).hasNext() );
235         }
236
237     public void testEmpty()
238         {
239         List bindings = ebList( empty, Q, none );
240         assertEquals( "testEmpty: select [] from {} => 1 empty binding [size]", bindings.size(), 1 );
241         Domain d = (Domain) bindings.get( 0 );
242         assertEquals( "testEmpty: select [] from {} => 1 empty binding [width]", d.size(), 0 );
243         }
244         
245     public void testOneMatch()
246         {
247         Q.addMatch( X, Query.ANY, Query.ANY );
248         List bindings = ebList( single, Q, justX );
249         assertEquals( "select X from {spindizzies drive cities} => 1 binding [size]", bindings.size(), 1 );
250         Domain d = (Domain) bindings.get( 0 );
251         assertEquals( "select X from {spindizzies drive cities} => 1 binding [width]", d.size(), 1 );
252         assertTrue( "select X from {spindizzies drive cities} => 1 binding [value]", d.get( 0 ).equals( node( "spindizzies" ) ) );
253         }
254         
255     public void testMismatch()
256         {
257         Q.addMatch( X, X, X );
258         List bindings = ebList( single, Q, justX );
259         assertEquals( "bindings mismatch (X X X)", bindings.size(), 0 );
260         }
261         
262     public void testXXXMatch1()
263         {
264         Q.addMatch( X, X, X );
265         Graph xxx = getGraphWith( "ring ring ring" );
266         List bindings = ebList( xxx, Q, justX );
267         assertEquals( "bindings match (X X X)", bindings.size(), 1 );
268         }
269
270     public void testXXXMatch3()
271         {
272         Q.addMatch( X, X, X );
273         Graph xxx = getGraphWith( "ring ring ring; ding ding ding; ping ping ping" );
274         List bindings = ebList( xxx, Q, justX );
275         assertEquals( "bindings match (X X X)", bindings.size(), 3 );
276     /* */
277         Set found = CollectionFactory.createHashedSet();
278         for (int i = 0; i < bindings.size(); i += 1)
279             {
280             Domain d = (Domain) bindings.get( i );
281             assertEquals( "one bound variable", d.size(), 1 );
282             found.add( d.get( 0 ) );
283             }
284         Set wanted = nodeSet( "ring ding ping" );
285         assertEquals( "testMatch getting {ring ding ping}", found, wanted );
286         }
287         
288     public void testTwoPatterns()
289         {
290         Node reads = node("reads"), inGenre = node("inGenre");
291         Graph g = getGraphWith( "chris reads blish; blish inGenre SF" );
292         // System.err.println( "| X = " + X + ", Y = " + Y + ", Z = " + Z );
293
Q.addMatch( X, reads, Y );
294         Q.addMatch( Y, inGenre, Z );
295         List bindings = ebList( g, Q, new Node [] {X, Z} );
296         assertTrue( "testTwoPatterns: one binding", bindings.size() == 1 );
297         Domain d = (Domain) bindings.get( 0 );
298         // System.out.println( "* width = " + d.width() );
299
assertTrue( "testTwoPatterns: width 2", d.size() >= 2 );
300         assertEquals( "testTwoPatterns: X = chris", d.get(0), node("chris") );
301         assertEquals( "testTwoPatterns: Y = SF", d.get(1), node("SF") );
302         }
303         
304     public void testGraphQuery()
305         {
306         Graph pattern = getGraphWith( "?X reads ?Y; ?Y inGenre ?Z" );
307         Graph target = getGraphWith( "chris reads blish; blish inGenre SF" );
308         // System.err.println( "| pattern: " + pattern );
309
Query q = new Query( pattern );
310         List bindings = ebList( target, q, new Node [] {node("?X"), node("?Z")} );
311         assertEquals( "testTwoPatterns: one binding", 1, bindings.size() );
312         Domain d = (Domain) bindings.get( 0 );
313         // System.out.println( "* width = " + d.width() );
314
assertTrue( "testTwoPatterns: width 2", d.size() >= 2 );
315         assertEquals( "testTwoPatterns: X = chris", d.get(0), node("chris") );
316         assertEquals( "testTwoPatterns: Y = SF", d.get(1), node("SF") );
317         }
318                 
319     public void testTwoGraphs()
320         {
321         Graph a = getGraphWith( "chris reads blish; chris reads norton; chris eats curry" );
322         Graph b = getGraphWith( "blish inGenre SF; curry inGenre food" );
323         Node reads = node("reads"), inGenre = node("inGenre");
324         Q.addMatch( "a", X, reads, Y ).addMatch( "b", Y, inGenre, Z );
325         NamedGraphMap args = Q.args().put( "a", a ).put( "b", b );
326         List bindings = iteratorToList( Q.executeBindings( args, new Node [] {X, Z} ) ); // TODO
327
assertEquals( "testTwoGraphs: one binding", bindings.size(), 1 );
328         Domain d = (Domain) bindings.get( 0 );
329         assertTrue( "testTwoGraphs: width 2", d.size() >= 2 );
330         assertEquals( "testTwoGraphs: X = chris", d.get(0), node("chris") );
331         assertEquals( "testTwoGraphs: Y = SF", d.get(1), node("SF") );
332         }
333                 
334     public void testGraphConstraints( String JavaDoc title, Expression constraint, String JavaDoc wanted )
335         {
336         Query Q = new Query()
337             .addMatch( Query.ANY, Query.ANY, O )
338             .addConstraint( constraint );
339         Graph G = getGraphWith( "pigs fly south; dogs fly badly; plans fly flat" );
340         Set results = iteratorToSet( eb( G, Q, new Node[] {O} ).mapWith( getFirst ) );
341         assertEquals( "tgs", nodeSet( wanted ), results );
342         }
343         
344      public void testGraphConstraints()
345         {
346         Node badly = node( "badly" ), flat = node( "flat" );
347         testGraphConstraints( "tgs A", Expression.TRUE, "south flat badly" );
348         testGraphConstraints( "tgs B", notEqual( O, badly ), "south flat" );
349         testGraphConstraints( "tgs C", Dyadic.and( notEqual( O, badly ), notEqual( O, flat ) ), "south" );
350         }
351         
352     private void helpConstraint( String JavaDoc title, Expression constraints, int n )
353         {
354         Query q = new Query();
355         Graph g = getGraphWith( "blish wrote CIF; blish wrote VOR; hambly wrote Darwath; feynman mechanicked quanta" );
356         q.addMatch( X, node("wrote"), Query.ANY );
357         q.addConstraint( constraints );
358         List bindings = ebList( g, q, justX );
359         assertEquals( "testConstraint " + title + ": number of bindings", n, bindings.size() );
360         }
361         
362     public void testConstraint()
363         {
364         helpConstraint( "none", Expression.TRUE, 3 );
365         helpConstraint( "X /= blish", notEqual( X, node( "blish" ) ), 1 );
366         helpConstraint( "X /= blish & X /= hambly", Dyadic.and( notEqual( X, node( "blish" ) ), notEqual( X, node( "hambly" ) ) ), 0 );
367         }
368
369     private void helpConstraintThree( String JavaDoc title, Expression c, int n )
370         {
371         Query q = new Query();
372         Graph g = getGraphWith( "brust wrote jhereg; hedgehog hacked code; angel age 230; brust wrote 230" );
373         q.addConstraint( c );
374         q.addMatch( X, Y, Z );
375         List bindings = ebList( g, q, new Node [] {X, Z} );
376         assertEquals( "testConstraint " + title + ": number of bindings", n, bindings.size() );
377         }
378         
379     public void testConstraintThree()
380         {
381         helpConstraintThree( "testConstraintThree 1:", areEqual( X, node( "brust" ) ), 2 );
382         helpConstraintThree( "testConstraintThree 2:", areEqual( Y, node( "hacked" ) ), 1 );
383         helpConstraintThree( "testConstraintThree 3:", areEqual( Z, node( "230" ) ), 2 );
384        }
385        
386    public void testConstraintFour()
387         {
388         Query q = new Query();
389         Graph g = getGraphWith( "bill pinged ben; ben pinged weed; weed pinged weed; bill ignored bill" );
390         q.addMatch( X, node("pinged"), Y );
391         q.addConstraint( notEqual( X, Y ) );
392         Set bindings = iteratorToSet( eb( g, q, justX ).mapWith(getFirst) );
393         assertEquals( arrayToSet( new Node[] {node("bill"), node("ben")} ), bindings );
394         }
395        
396    /**
397         Test that the MATCHES constraint works.
398     */

399    public void testMatchConstraint()
400         {
401         Set expected = CollectionFactory.createHashedSet();
402         expected.add( node( "beta" ) );
403         Query q = new Query()
404             .addMatch( X, node( "ppp" ), Y ).addConstraint( matches( Y, node( "'ell'" ) ) )
405             ;
406         Graph g = getGraphWith( "alpha ppp beta; beta ppp 'hello'; gamma ppp 'goodbye'" );
407         Set bindings = iteratorToSet( eb( g, q, justX ).mapWith( getFirst ) );
408         assertEquals( expected, bindings );
409         }
410         
411     /**
412         Test that a PatternStage extracts appropriate parts of a constraint set.
413     */

414     public void testExtractConstraint()
415         {
416             // Surely there should be something here?
417
}
418         
419     public void testStringResults()
420         {
421         Graph g = getGraphWith( "ding dong dilly" );
422         Query q = new Query() .addMatch( X, Y, Query.ANY );
423         List bindings = ebList( g, q, new Node [] {X, Y} );
424         assertEquals( "one result back by name", bindings.size(), 1 );
425         assertEquals( "x = ding", ((Domain) bindings.get(0)).get(0), node("ding") );
426         }
427         
428     /**
429         this possible failure mode discovered by Andy when building a fast-path
430         RDQL engine over the graph.query SPI.
431     <br>
432         test that we get a sensible result when unbound variables are used in the
433         query result selector.
434     */

435     public void testMissingVariable()
436         {
437         Graph g = getGraphWith( "x y z" );
438         List bindings = ebList( g, Q, new Node [] {X, Y} );
439         List L = (List) bindings.get(0);
440         assertEquals( "undefined variables get null", null, L.get( 0 ) );
441         }
442         
443     /**
444         More of an example than a test, for a query with "disconnected" triples.
445     */

446     public void testDisconnected()
447         {
448         Graph g = getGraphWith( "x pred1 foo; y pred2 bar" );
449         Query q = new Query( getGraphWith( "?X ?? foo; ?Y ?? bar" ) );
450         List bindings = ebList( g, q, nodes( "?X ?Y" ) );
451         assertEquals( 1, bindings.size() );
452         assertEquals( node( "x" ), ((Domain) bindings.get(0)).get(0) );
453         assertEquals( node( "y" ), ((Domain) bindings.get(0)).get(1) );
454         }
455         
456      /**
457         Test that the default engine does not re-order triples.
458      */

459     public void testQueryTripleOrder()
460         {
461         Triple t1 = Triple.create( "A B C" ), t2 = Triple.create( "D E F" );
462         List desired = Arrays.asList( new Triple[] {t1, t2} );
463         List obtained = getTriplesFromQuery( desired );
464         assertEquals( desired, obtained );
465         }
466         
467     /**
468         This horror to extract the order in which the triples are handed to
469         patternStage illustrates that the Query code needs some refactoring
470         to make it more testable.
471         TODO make the Query code more testable.
472     */

473     private List getTriplesFromQuery( List desired )
474         {
475         Query q = new Query();
476         final Triple [][] tripleses = new Triple[1][];
477         final Graph g = new GraphBase()
478             {
479             public ExtendedIterator graphBaseFind( TripleMatch tm )
480                 { return NullIterator.instance; }
481             public QueryHandler queryHandler()
482                 {
483                 return new SimpleQueryHandler( this )
484                     {
485                     public Stage patternStage( Mapping map, ExpressionSet constraints, Triple [] t )
486                         {
487                         if (t.length > 1) tripleses[0] = t;
488                         return super.patternStage( map, constraints, t );
489                         }
490                     }
491                     ;
492                 }
493             };
494         for (int i = 0; i < desired.size(); i += 1) q.addMatch( (Triple) desired.get(i) );
495         eb( g, q, none );
496         return Arrays.asList( tripleses[0] );
497         }
498         
499     /**
500         test that we can correctly deduce the variable count for some queries.
501      */

502     public void testVariableCount()
503         {
504         assertCount( 0, "" );
505         assertCount( 0, "x R y" );
506         assertCount( 1, "?x R y" );
507         assertCount( 1, "?x R y", "?x" );
508         assertCount( 2, "?x R y", "?z" );
509         assertCount( 1, "?x R ?x" );
510         assertCount( 2, "?x R ?y" );
511         assertCount( 3, "?x R ?y", "?z" );
512         assertCount( 3, "?x ?R ?y" );
513         assertCount( 6, "?x ?R ?y; ?a ?S ?c" );
514         assertCount( 6, "?x ?R ?y; ?a ?S ?c", "?x" );
515         assertCount( 6, "?x ?R ?y; ?a ?S ?c", "?x ?c" );
516         assertCount( 6, "?x ?R ?y; ?a ?S ?c", "?x ?y ?c" );
517         assertCount( 7, "?x ?R ?y; ?a ?S ?c", "?dog" );
518         assertCount( 8, "?x ?R ?y; ?a ?S ?c", "?dog ?cat ?x" );
519         assertCount( 18, "?a ?b ?c; ?d ?e ?f; ?g ?h ?i; ?j ?k ?l; ?m ?n ?o; ?p ?q ?r" );
520         }
521     
522     public void assertCount( int expected, String JavaDoc query )
523         { assertCount( expected, query, "" ); }
524         
525     public void assertCount( int expected, String JavaDoc query, String JavaDoc vars )
526         {
527         Graph g = getGraphWith( "" );
528         Query q = new Query();
529         Triple [] triples = tripleArray( query );
530         for (int i = 0; i < triples.length; i += 1) q.addMatch( triples[i] );
531         // eb( g, q, nodes( vars ) );
532
q.executeBindings( g, nodes( vars ) );
533         assertEquals( expected, q.getVariableCount() );
534         }
535         
536     /**
537         test that unbound constraint variables are handled "nicely".
538     */

539     public void testQueryConstraintUnbound()
540         {
541         Query q = new Query()
542             .addConstraint( notEqual( X, Z ) )
543             .addMatch( X, Query.ANY, X )
544             ;
545         Graph g = getGraphWith( "x R x; x R y" );
546         try
547             {
548             ExtendedIterator it = eb( g, q, justX );
549             fail( "should spot unbound variable" );
550             }
551         catch (Query.UnboundVariableException b) { pass(); }
552         }
553         
554     public void testCloseQuery()
555         {
556         Graph g = getGraphWith( "x R y; a P b; i L j; d X f; h S g; no more heroes" );
557         for (int n = 0; n < 1000; n += 1) graphAdd( g, "ping pong X" + n );
558         Query q = new Query().addMatch( Query.S, Query.P, Query.O );
559         List stages = new ArrayList();
560         ExtendedIterator it = eb( g, q, nodes( "?P" ) );
561         /* eat one answer to poke pipe */ it.next();
562         for (int i = 0; i < stages.size(); i += 1) assertFalse( ((Stage) stages.get(i)).isClosed() );
563         it.close();
564         for (int i = 0; i < stages.size(); i += 1) assertTrue( ((Stage) stages.get(i)).isClosed() );
565         }
566         
567     public void testRewriteStartswithExpression()
568         {
569         Query q = new Query();
570         Expression L = constant( "x" );
571         Expression R = createSimplePattern( "^begins" );
572         Expression provided = dyadic( L, "Q_StringMatch", R );
573         Expression desired = dyadic( L, "J_startsWith", constant( "begins" ) );
574         q.addConstraint( provided );
575         Expression e2 = (Expression) q.getConstraints().iterator().next();
576         assertEquals( desired, e2 );
577         }
578
579     public void testRewriteStartswithInsensitiveExpression()
580         {
581         Query q = new Query();
582         Expression L = constant( "x" );
583         Expression R = createModifiedPattern( "^begins", "i" );
584         Expression provided = dyadic( L, "Q_StringMatch", R );
585         Expression desired = dyadic( L, "J_startsWithInsensitive", constant( "begins" ) );
586         q.addConstraint( provided );
587         Expression e2 = (Expression) q.getConstraints().iterator().next();
588         assertEquals( desired, e2 );
589         }
590
591     public void testRewriteEndswithExpression()
592         {
593         Query q = new Query();
594         Expression L = constant( "x" );
595         Expression R = createSimplePattern( "ends$" );
596         Expression provided = dyadic( L, "Q_StringMatch", R );
597         Expression desired = dyadic( L, "J_endsWith", constant( "ends" ) );
598         q.addConstraint( provided );
599         Expression e2 = (Expression) q.getConstraints().iterator().next();
600         assertEquals( desired, e2 );
601         }
602    
603     public void testRewriteEndswithInsensitiveExpression()
604         {
605         Query q = new Query();
606         Expression L = constant( "x" );
607         Expression R = createModifiedPattern( "ends$", "i" );
608         Expression provided = dyadic( L, "Q_StringMatch", R );
609         Expression desired = dyadic( L, "J_endsWithInsensitive", constant( "ends" ) );
610         q.addConstraint( provided );
611         Expression e2 = (Expression) q.getConstraints().iterator().next();
612         assertEquals( desired, e2 );
613         }
614    
615     public void testRewriteContainsExpression()
616         {
617         Query q = new Query();
618         Expression L = constant( "x" );
619         Expression R = createSimplePattern( "contains" );
620         Expression provided = dyadic( L, "Q_StringMatch", R );
621         Expression desired = dyadic( L, "J_contains", constant( "contains" ) );
622         q.addConstraint( provided );
623         Expression e2 = (Expression) q.getConstraints().iterator().next();
624         assertEquals( desired, e2 );
625         }
626     
627     public void testRewriteContainsInsensitiveExpression()
628         {
629         Query q = new Query();
630         Expression L = constant( "x" );
631         Expression R = createModifiedPattern( "coNtaIns", "i" );
632         Expression provided = dyadic( L, "Q_StringMatch", R );
633         Expression desired = dyadic( L, "J_containsInsensitive", constant( "contains" ) );
634         q.addConstraint( provided );
635         Expression e2 = (Expression) q.getConstraints().iterator().next();
636         assertEquals( desired, e2 );
637         }
638
639     protected static class BangException extends JenaException
640         {
641         public BangException() { super( "bang!" ); }
642         }
643     
644     public void testQueryExceptionCleanlyExits()
645         {
646         Query q = new Query().addMatch( Triple.ANY );
647         Graph g = new GraphBase()
648             {
649             protected ExtendedIterator graphBaseFind( TripleMatch m )
650                 { throw new BangException(); }
651             };
652         ExtendedIterator it = eb( g, q, new Node[] {} );
653         try { it.next(); fail( "should fail because graph explodes" ); }
654         catch (QueryStageException e) { assertTrue( e.getCause() instanceof BangException ); }
655         catch (Exception JavaDoc e) { fail( "should throw QueryStageException" ); }
656         }
657     
658     protected static class PL extends Expression.Fixed implements PatternLiteral
659         {
660         protected String JavaDoc modifiers = "";
661         public PL( String JavaDoc content ) { super( content ); }
662         public PL( String JavaDoc content, String JavaDoc modifiers ) { super( content ); this.modifiers = modifiers; }
663         public String JavaDoc getPatternString() { return (String JavaDoc) value; }
664         public String JavaDoc getPatternModifiers() { return modifiers; }
665         public String JavaDoc getPatternLanguage() { return rdql; }
666         }
667     
668     public Expression createSimplePattern( final String JavaDoc p )
669         { return new PL( p ); }
670     
671     public Expression createModifiedPattern( String JavaDoc content, String JavaDoc modifiers )
672         { return new PL( content, modifiers ); }
673     
674     private Expression constant( final Object JavaDoc it )
675         { return new Expression.Fixed( it ); }
676
677     private Expression dyadic( Expression l, String JavaDoc op, Expression r )
678         {
679         final String JavaDoc f = ExpressionFunctionURIs.prefix + op;
680         return new Dyadic( l, f, r )
681             {
682             public boolean evalBool( Object JavaDoc l, Object JavaDoc r )
683                 { return false; }
684             };
685         }
686
687     /**
688         Test that a variety of triple-sorters make no difference to the results of a query
689         over a moderately interesting graph.
690     */

691     public void testTripleSorting()
692         {
693         Graph g = dataGraph();
694         Map answer = getAnswer( g, TripleSorter.dontSort );
695         assertEquals( 1, answer.size() );
696         assertEquals( new Integer JavaDoc(1), answer.get( Arrays.asList( nodes( "a d" ) ) ) );
697     /* */
698         assertEquals( answer, getAnswer( g, TripleSorter.dontSort ) );
699         assertEquals( answer, getAnswer( g, fiddle( 0, 2, 1 ) ) );
700         assertEquals( answer, getAnswer( g, fiddle( 1, 0, 2 ) ) );
701         assertEquals( answer, getAnswer( g, fiddle( 1, 2, 0 ) ) );
702         assertEquals( answer, getAnswer( g, fiddle( 2, 1, 0 ) ) );
703         assertEquals( answer, getAnswer( g, fiddle( 2, 0, 1 ) ) );
704         }
705         
706     protected TripleSorter fiddle( final int a, final int b, final int c )
707         {
708         return new TripleSorter()
709             {
710             public Triple [] sort( Triple [] triples )
711                 { return new Triple[] {triples[a], triples[b], triples[c]}; }
712             };
713         }
714
715     protected Graph dataGraph()
716         {
717         Graph result = getGraph();
718         graphAdd( result, "a SPOO d; a X b; b Y c" );
719         return result;
720         }
721         
722     protected Map getAnswer( Graph g, TripleSorter sorter )
723         {
724         Map result = CollectionFactory.createHashedMap();
725         Query q = new Query();
726         q.addMatch( triple( "?a ?? ?d " ) ).addMatch( triple( "?a X ?b" ) ).addMatch( triple( "?b Y ?c" ) );
727         q.addConstraint( notEqual( node( "?d" ), node( "?b" ) ) );
728         Node [] answers = nodes( "?a ?d" );
729         q.setTripleSorter( sorter );
730         ExtendedIterator it = eb( g, q, answers );
731         while (it.hasNext()) addAnswer( result, (List) it.next(), answers.length );
732         return result;
733         }
734         
735     protected void addAnswer( Map result, List bindings, int limit )
736         {
737         List key = bindings.subList( 0, limit );
738         Integer JavaDoc already = (Integer JavaDoc) result.get( key );
739         if (already == null) already = new Integer JavaDoc( 0 );
740         result.put( key, new Integer JavaDoc( already.intValue() + 1 ) );
741         }
742     
743     public void testQueryOptimisation()
744         {
745         int dontCount = queryCount( TripleSorter.dontSort );
746         int optimCount = queryCount( new SimpleTripleSorter() );
747         // System.err.println( ">> dontCount=" + dontCount + " optimCount=" + optimCount );
748
if (optimCount > dontCount)
749             fail( "optimisation " + optimCount + " yet plain " + dontCount );
750         }
751       
752     int queryCount( TripleSorter sort )
753         {
754         CountingGraph g = bigCountingGraph();
755         for (int a = 0; a < 10; a += 1)
756             for (int b = 0; b < 10; b += 1)
757                 for (int X = 0; X < 3; X += 1)
758                     graphAdd( g, "a" + a + " X" + (X == 0 ? "" : X + "") + " b" + b );
759         graphAdd( g, "a SPOO d; a X b; b Y c" );
760         getAnswer( g, sort );
761         return g.getCount();
762         }
763         
764     static class CountingGraph extends WrappedGraph
765         {
766         int counter;
767         private QueryHandler qh;
768         public QueryHandler queryHandler( ) { return qh; }
769         CountingGraph( Graph base )
770             { super( base ); qh = new SimpleQueryHandler( this ); }
771         public ExtendedIterator find( Node s, Node p, Node o )
772             { return find( Triple.createMatch( s, p, o ) ); }
773         public ExtendedIterator find( TripleMatch tm )
774             { return count( base.find( tm ) ); }
775         ExtendedIterator count( ExtendedIterator it )
776             {
777             return new WrappedIterator( it )
778                 {
779                 public Object JavaDoc next() { try { return super.next(); } finally { counter += 1; } }
780                 };
781             }
782         int getCount()
783             { return counter; }
784         public String JavaDoc toString()
785             { return base.toString(); }
786         }
787         
788     CountingGraph bigCountingGraph()
789         {
790         Graph bigGraph = getGraph();
791         return new CountingGraph( bigGraph );
792         }
793     }
794
795
796 /*
797     (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
798     All rights reserved.
799
800     Redistribution and use in source and binary forms, with or without
801     modification, are permitted provided that the following conditions
802     are met:
803
804     1. Redistributions of source code must retain the above copyright
805        notice, this list of conditions and the following disclaimer.
806
807     2. Redistributions in binary form must reproduce the above copyright
808        notice, this list of conditions and the following disclaimer in the
809        documentation and/or other materials provided with the distribution.
810
811     3. The name of the author may not be used to endorse or promote products
812        derived from this software without specific prior written permission.
813
814     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
815     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
816     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
817     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
818     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
819     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
820     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
821     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
822     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
823     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
824 */
Popular Tags