KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > reasoner > rulesys > test > TestBasics


1 /******************************************************************
2  * File: TestBasics.java
3  * Created by: Dave Reynolds
4  * Created on: 30-Mar-03
5  *
6  * (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
7  * [See end of file]
8  * $Id: TestBasics.java,v 1.25 2005/02/21 12:18:10 andy_seaborne Exp $
9  *****************************************************************/

10 package com.hp.hpl.jena.reasoner.rulesys.test;
11
12 import com.hp.hpl.jena.mem.GraphMem;
13 import com.hp.hpl.jena.rdf.model.*;
14 import com.hp.hpl.jena.reasoner.*;
15 import com.hp.hpl.jena.reasoner.rulesys.*;
16 import com.hp.hpl.jena.reasoner.rulesys.impl.*;
17 import com.hp.hpl.jena.reasoner.test.TestUtil;
18 import com.hp.hpl.jena.graph.*;
19 import com.hp.hpl.jena.util.PrintUtil;
20 import com.hp.hpl.jena.vocabulary.*;
21
22 import junit.framework.TestCase;
23 import junit.framework.TestSuite;
24 import java.util.*;
25 import java.io.*;
26
27 /**
28  * Unit tests for simple infrastructure pieces of the rule systems.
29  *
30  * @author <a HREF="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
31  * @version $Revision: 1.25 $ on $Date: 2005/02/21 12:18:10 $
32  */

33 public class TestBasics extends TestCase {
34     // Useful constants
35
Node p = Node.createURI("p");
36     Node q = Node.createURI("q");
37     Node r = Node.createURI("r");
38     Node s = Node.createURI("s");
39     Node n1 = Node.createURI("n1");
40     Node n2 = Node.createURI("n2");
41     Node n3 = Node.createURI("n3");
42     Node n4 = Node.createURI("n4");
43     Node n5 = Node.createURI("n5");
44     Node res = Node.createURI("res");
45         
46      
47     /**
48      * Boilerplate for junit
49      */

50     public TestBasics( String JavaDoc name ) {
51         super( name );
52     }
53     
54     /**
55      * Boilerplate for junit.
56      * This is its own test suite
57      */

58     public static TestSuite suite() {
59         return new TestSuite( TestBasics.class );
60     }
61
62     /**
63      * Test the internal rule parser
64      */

65     public void testRuleParser() {
66        String JavaDoc[] testRules = new String JavaDoc[] {
67             "(?a rdf:type ?_) -> (?a rdf:type ?b).",
68             "(?a rdf:type ?_), (?a rdf:type ?_) -> (?a rdf:type ?b).",
69             "(?a rdf:type max(?a,1)) -> (?a rdf:type 'foo').",
70             "(?a rdf:type ?_) -> addOne(?a).",
71             "(?a rdf:type ?_) -> [(?a rdf:type ?_) -> addOne(?a)].",
72            "(?a rdf:type ?_) -> (?a rdf:type '42').",
73            "(?a rdf:type ?_) -> (?a rdf:type 4.2).",
74            "(?a rdf:type ?_) -> (?a rdf:type ' fool that,I(am)').",
75             "[rule1: (?a rdf:type ?_) -> (?a rdf:type a)]"
76         };
77         String JavaDoc[] testResults = new String JavaDoc[] {
78             "[ (?a rdf:type ?_) -> (?a rdf:type ?b) ]",
79             "[ (?a rdf:type ?_) (?a rdf:type ?_) -> (?a rdf:type ?b) ]",
80             "[ (?a rdf:type max(?a 1^^http://www.w3.org/2001/XMLSchema#int)^^urn:x-hp-jena:Functor) -> (?a rdf:type 'foo') ]",
81             "[ (?a rdf:type ?_) -> addOne(?a) ]",
82             "[ (?a rdf:type ?_) -> [ (?a rdf:type ?_) -> addOne(?a) ] ]",
83             "[ (?a rdf:type ?_) -> (?a rdf:type '42') ]",
84             "[ (?a rdf:type ?_) -> (?a rdf:type 4.2^^http://www.w3.org/2001/XMLSchema#float) ]",
85             "[ (?a rdf:type ?_) -> (?a rdf:type ' fool that,I(am)') ]",
86             "[ rule1: (?a rdf:type ?_) -> (?a rdf:type a) ]"
87         };
88         
89         for (int i = 0; i < testRules.length; i++) {
90             Rule r = Rule.parseRule(testRules[i]);
91             assertEquals(testResults[i], r.toString());
92         }
93     }
94
95     /**
96      * Test rule equality operations.
97      */

98     public void testRuleEquality() {
99         Rule r1 = Rule.parseRule("(?a p ?b) -> (?a q ?b).");
100         Rule r2 = Rule.parseRule("(?a p ?b) -> (?b q ?a).");
101         Rule r1b = Rule.parseRule("(?x p ?y) -> (?x q ?y).");
102         Rule r3 = Rule.parseRule("(?a p ?b), addOne(?a) -> (?a q ?b).");
103         Rule r3b = Rule.parseRule("(?c p ?d), addOne(?c) -> (?c q ?d).");
104         Rule r4 = Rule.parseRule("(?a p ?b), makeTemp(?a) -> (?a q ?b).");
105         Rule r5 = Rule.parseRule("(?a p ?b), addOne(?b) -> (?a q ?b).");
106         Rule r6 = Rule.parseRule("(?a p ?b), addOne(p) -> (?a q ?b).");
107         assertTrue(! r1.equals(r2));
108         assertTrue( r1.equals(r1b));
109         assertTrue(! r1.equals(r3));
110         assertTrue( r3.equals(r3b));
111         assertTrue(! r3.equals(r4));
112         assertTrue(! r3.equals(r5));
113         assertTrue(! r3.equals(r6));
114     }
115     
116     /**
117      * Test the BindingEnvironment machinery
118      */

119     public void testBindingEnvironment() {
120         BindingStack env = new BindingStack();
121         
122         env.bind(3, n1);
123         assertEquals(n1, env.getEnvironment()[3]);
124         env.push();
125         env.bind(2, n2);
126         assertEquals(n2, env.getEnvironment()[2]);
127         env.unwind();
128         assertEquals(null, env.getEnvironment()[2]);
129         assertEquals(n1, env.getEnvironment()[3]);
130         env.push();
131         env.bind(1, n3);
132         assertEquals(null, env.getEnvironment()[2]);
133         assertEquals(n1, env.getEnvironment()[3]);
134         assertEquals(n3, env.getEnvironment()[1]);
135         env.unwind();
136         assertEquals(null, env.getEnvironment()[2]);
137         assertEquals(n1, env.getEnvironment()[3]);
138         assertEquals(null, env.getEnvironment()[1]);
139         env.push();
140         env.bind(1, n3);
141         assertEquals(null, env.getEnvironment()[2]);
142         assertEquals(n1, env.getEnvironment()[3]);
143         assertEquals(n3, env.getEnvironment()[1]);
144         env.commit();
145         assertEquals(null, env.getEnvironment()[2]);
146         assertEquals(n1, env.getEnvironment()[3]);
147         assertEquals(n3, env.getEnvironment()[1]);
148         try {
149             env.unwind();
150             assertTrue("Failed to catch end of stack", false);
151         } catch (IndexOutOfBoundsException JavaDoc e) {
152         }
153     }
154     
155     /**
156      * Test simple single clause binding
157      */

158     public void testClauseMaching() {
159         BindingStack env = new BindingStack();
160         List rules = new ArrayList();
161         BasicForwardRuleInfGraph inf = new BasicForwardRuleInfGraph(
162                                             new BasicForwardRuleReasoner(rules), rules, null);
163         TriplePattern p1 = new TriplePattern(
164                                     new Node_RuleVariable("?a", 0),
165                                     n1,
166                                     new Node_RuleVariable("?b", 1));
167         TriplePattern p2 = new TriplePattern(
168                                     new Node_RuleVariable("?b", 1),
169                                     new Node_RuleVariable("?c", 2),
170                                     n2);
171
172         // Should fail with no bindings
173
boolean match = FRuleEngine.match(p1, new Triple(n1, n2, n3), env);
174         assertTrue(!match);
175         assertEquals(null, env.getEnvironment()[0]);
176         assertEquals(null, env.getEnvironment()[1]);
177         assertEquals(null, env.getEnvironment()[2]);
178         
179         // Should succeed with two bindings
180
match = FRuleEngine.match(p1, new Triple(n2, n1, n3), env);
181         assertTrue(match);
182         assertEquals(n2, env.getEnvironment()[0]);
183         assertEquals(n3, env.getEnvironment()[1]);
184         assertEquals(null, env.getEnvironment()[2]);
185         
186         // should fail but leave prior bindings intact
187
match = FRuleEngine.match(p2, new Triple(n1, n2, n2), env);
188         assertTrue(!match);
189         assertEquals(n2, env.getEnvironment()[0]);
190         assertEquals(n3, env.getEnvironment()[1]);
191         assertEquals(null, env.getEnvironment()[2]);
192         
193         // should succeed with full binding set
194
match = FRuleEngine.match(p2, new Triple(n3, n1, n2), env);
195         assertTrue(match);
196         assertEquals(n2, env.getEnvironment()[0]);
197         assertEquals(n3, env.getEnvironment()[1]);
198         assertEquals(n1, env.getEnvironment()[2]);
199     }
200       
201     /**
202      * Minimal rule tester to check basic pattern match
203      */

204     public void testRuleMatcher() {
205         String JavaDoc rules = "[r1: (?a p ?b), (?b q ?c) -> (?a, q, ?c)]" +
206                        "[r2: (?a p ?b), (?b p ?c) -> (?a, p, ?c)]" +
207                        "[r3: (?a p ?a), (n1 p ?c), (n1, p, ?a) -> (?a, p, ?c)]" +
208                        "[r4: (n4 ?p ?a) -> (n4, ?a, ?p)]";
209         List ruleList = Rule.parseRules(rules);
210         
211         InfGraph infgraph = new BasicForwardRuleReasoner(ruleList).bind(new GraphMem());
212         infgraph.add(new Triple(n1, p, n2));
213         infgraph.add(new Triple(n2, p, n3));
214         infgraph.add(new Triple(n2, q, n3));
215         infgraph.add(new Triple(n4, p, n4));
216         
217         TestUtil.assertIteratorValues(this, infgraph.find(null, null, null),
218             new Triple[] {
219                 new Triple(n1, p, n2),
220                 new Triple(n2, p, n3),
221                 new Triple(n2, q, n3),
222                 new Triple(n4, p, n4),
223                 new Triple(n1, p, n3),
224                 new Triple(n1, q, n3),
225                 new Triple(n4, n4, p),
226             });
227     }
228       
229     /**
230      * Test derivation machinery
231      */

232     public void testRuleDerivations() {
233         String JavaDoc rules = "[testRule1: (n1 p ?a) -> (n2, p, ?a)]" +
234                        "[testRule2: (n1 q ?a) -> (n2, q, ?a)]" +
235                        "[testRule3: (n2 p ?a), (n2 q ?a) -> (res p ?a)]";
236         List ruleList = Rule.parseRules(rules);
237         
238         InfGraph infgraph = new BasicForwardRuleReasoner(ruleList).bind(new GraphMem());
239         infgraph.setDerivationLogging(true);
240         infgraph.add(new Triple(n1, p, n3));
241         infgraph.add(new Triple(n1, q, n4));
242         infgraph.add(new Triple(n1, q, n3));
243
244         TestUtil.assertIteratorValues(this, infgraph.find(null, null, null),
245             new Triple[] {
246                 new Triple(n1, p, n3),
247                 new Triple(n2, p, n3),
248                 new Triple(n1, q, n4),
249                 new Triple(n2, q, n4),
250                 new Triple(n1, q, n3),
251                 new Triple(n2, q, n3),
252                 new Triple(res, p, n3)
253             });
254         
255         Iterator derivs = infgraph.getDerivation(new Triple(res, p, n3));
256         StringWriter outString = new StringWriter(250);
257         PrintWriter out = new PrintWriter(outString);
258         while (derivs.hasNext()) {
259             Derivation d = (Derivation) derivs.next();
260             d.printTrace(out, true);
261         }
262         out.flush();
263         
264         String JavaDoc testString = TestUtil.normalizeWhiteSpace("Rule testRule3 concluded (res p n3) <-\n" +
265                 " Rule testRule1 concluded (n2 p n3) <-\n" +
266                 " Fact (n1 p n3)\r\n" +
267                 " Rule testRule2 concluded (n2 q n3) <-\n" +
268                 " Fact (n1 q n3)\r\n");
269         assertEquals(testString, TestUtil.normalizeWhiteSpace(outString.getBuffer().toString()));
270     }
271     
272           
273     /**
274      * Test axiom handling machinery
275      */

276     public void testAxiomHandling() {
277         String JavaDoc rules = "[testRule1: (n1 p ?a) -> (n2, p, ?a)]" +
278                        "[testRule2: (n1 q ?a) -> (n2, q, ?a)]" +
279                        "[testRule3: (n2 p ?a), (n2 q ?a) -> (res p ?a)]" +
280                        "[axiom1: -> (n1 p n3)]";
281         List ruleList = Rule.parseRules(rules);
282         
283         InfGraph infgraph = new BasicForwardRuleReasoner(ruleList).bind(new GraphMem());
284         TestUtil.assertIteratorValues(this, infgraph.find(null, null, null),
285             new Triple[] {
286                 new Triple(n1, p, n3),
287                 new Triple(n2, p, n3),
288             });
289         
290         infgraph.add(new Triple(n1, q, n4));
291         infgraph.add(new Triple(n1, q, n3));
292
293         TestUtil.assertIteratorValues(this, infgraph.find(null, null, null),
294             new Triple[] {
295                 new Triple(n1, p, n3),
296                 new Triple(n2, p, n3),
297                 new Triple(n1, q, n4),
298                 new Triple(n2, q, n4),
299                 new Triple(n1, q, n3),
300                 new Triple(n2, q, n3),
301                 new Triple(res, p, n3)
302             });
303         
304     }
305      
306     /**
307      * Test schema partial binding machinery
308      */

309     public void testSchemaBinding() {
310         String JavaDoc rules = "[testRule1: (n1 p ?a) -> (n2, p, ?a)]" +
311                        "[testRule2: (n1 q ?a) -> (n2, q, ?a)]" +
312                        "[testRule3: (n2 p ?a), (n2 q ?a) -> (res p ?a)]";
313         List ruleList = Rule.parseRules(rules);
314         Graph schema = new GraphMem();
315         schema.add(new Triple(n1, p, n3));
316         Graph data = new GraphMem();
317         data.add(new Triple(n1, q, n4));
318         data.add(new Triple(n1, q, n3));
319         
320         Reasoner reasoner = new BasicForwardRuleReasoner(ruleList);
321         Reasoner boundReasoner = reasoner.bindSchema(schema);
322         InfGraph infgraph = boundReasoner.bind(data);
323
324         TestUtil.assertIteratorValues(this, infgraph.find(null, null, null),
325             new Triple[] {
326                 new Triple(n1, p, n3),
327                 new Triple(n2, p, n3),
328                 new Triple(n1, q, n4),
329                 new Triple(n2, q, n4),
330                 new Triple(n1, q, n3),
331                 new Triple(n2, q, n3),
332                 new Triple(res, p, n3)
333             });
334     }
335     
336     /**
337      * Test functor handling
338      */

339     public void testEmbeddedFunctors() {
340         String JavaDoc rules = "(?C rdf:type owl:Restriction), (?C owl:onProperty ?P), (?C owl:allValuesFrom ?D) -> (?C rb:restriction all(?P, ?D))." +
341                        "(?C rb:restriction all(eg:p, eg:D)) -> (?C rb:restriction 'allOK')." +
342                        "[ -> (eg:foo eg:prop functor(eg:bar, 1)) ]" +
343                        "[ (?x eg:prop functor(eg:bar, ?v)) -> (?x eg:propbar ?v) ]" +
344                        "[ (?x eg:prop functor(?v, ?*)) -> (?x eg:propfunc ?v) ]" +
345                        "";
346         List ruleList = Rule.parseRules(rules);
347         
348         Model data = ModelFactory.createDefaultModel();
349         Resource R1 = data.createResource(PrintUtil.egNS + "R1");
350         Resource D = data.createResource(PrintUtil.egNS + "D");
351         Property p = data.createProperty(PrintUtil.egNS, "p");
352         Property prop = data.createProperty(PrintUtil.egNS, "prop");
353         Property propbar = data.createProperty(PrintUtil.egNS, "propbar");
354         Property propfunc = data.createProperty(PrintUtil.egNS, "propfunc");
355         Property rbr = data.createProperty(ReasonerVocabulary.RBNamespace, "restriction");
356         R1.addProperty(RDF.type, OWL.Restriction)
357           .addProperty(OWL.onProperty, p)
358           .addProperty(OWL.allValuesFrom, D);
359         
360         Reasoner reasoner = new BasicForwardRuleReasoner(ruleList);
361         InfGraph infgraph = reasoner.bind(data.getGraph());
362         Model infModel = ModelFactory.createModelForGraph(infgraph);
363         Resource foo = infModel.createResource(PrintUtil.egNS + "foo");
364         Resource bar = infModel.createResource(PrintUtil.egNS + "bar");
365         
366         RDFNode flit = infModel.getResource(R1.getURI()).getRequiredProperty(rbr).getObject();
367         assertNotNull(flit);
368         assertEquals(flit.toString(), "allOK");
369 // assertTrue(flit instanceof Literal);
370
// Functor func = (Functor)((Literal)flit).getValue();
371
// assertEquals("all", func.getName());
372
// assertEquals(p.getNode(), func.getArgs()[0]);
373
// assertEquals(D.getNode(), func.getArgs()[1]);
374

375         Literal one = (Literal)foo.getRequiredProperty(propbar).getObject();
376         assertEquals(new Integer JavaDoc(1), one.getValue());
377     }
378     
379     /**
380      * The the minimal machinery for supporting builtins
381      */

382     public void testBuiltins() {
383         String JavaDoc rules = //"[testRule1: (n1 ?p ?a) -> print('rule1test', ?p, ?a)]" +
384
"[r1: (n1 p ?x), addOne(?x, ?y) -> (n1 q ?y)]" +
385                        "[r2: (n1 p ?x), lessThan(?x, 3) -> (n2 q ?x)]" +
386                        "[axiom1: -> (n1 p 1)]" +
387                        "[axiom2: -> (n1 p 4)]" +
388                        "";
389         List ruleList = Rule.parseRules(rules);
390         
391         InfGraph infgraph = new BasicForwardRuleReasoner(ruleList).bind(new GraphMem());
392         TestUtil.assertIteratorValues(this, infgraph.find(n1, q, null),
393             new Triple[] {
394                 new Triple(n1, q, Util.makeIntNode(2)),
395                 new Triple(n1, q, Util.makeIntNode(5))
396             });
397         TestUtil.assertIteratorValues(this, infgraph.find(n2, q, null),
398             new Triple[] {
399                 new Triple(n2, q, Util.makeIntNode(1))
400             });
401         
402     }
403     
404     /**
405      * The the "remove" builtin
406      */

407     public void testRemoveBuiltin() {
408         String JavaDoc rules =
409                        "[rule1: (?x p ?y), (?x q ?y) -> remove(0)]" +
410                        "";
411         List ruleList = Rule.parseRules(rules);
412
413         InfGraph infgraph = new BasicForwardRuleReasoner(ruleList).bind(new GraphMem());
414         infgraph.add(new Triple(n1, p, Util.makeIntNode(1)));
415         infgraph.add(new Triple(n1, p, Util.makeIntNode(2)));
416         infgraph.add(new Triple(n1, q, Util.makeIntNode(2)));
417         
418         TestUtil.assertIteratorValues(this, infgraph.find(n1, null, null),
419             new Triple[] {
420                 new Triple(n1, p, Util.makeIntNode(1)),
421                 new Triple(n1, q, Util.makeIntNode(2))
422             });
423         
424     }
425     
426     /**
427      * Test the rebind operation.
428      */

429     public void testRebind() {
430         String JavaDoc rules = "[rule1: (?x p ?y) -> (?x q ?y)]";
431         List ruleList = Rule.parseRules(rules);
432         Graph data = new GraphMem();
433         data.add(new Triple(n1, p, n2));
434         InfGraph infgraph = new BasicForwardRuleReasoner(ruleList).bind(data);
435         TestUtil.assertIteratorValues(this, infgraph.find(n1, null, null),
436             new Triple[] {
437                 new Triple(n1, p, n2),
438                 new Triple(n1, q, n2)
439             });
440         Graph ndata = new GraphMem();
441         ndata.add(new Triple(n1, p, n3));
442         infgraph.rebind(ndata);
443         TestUtil.assertIteratorValues(this, infgraph.find(n1, null, null),
444             new Triple[] {
445                 new Triple(n1, p, n3),
446                 new Triple(n1, q, n3)
447             });
448     }
449     
450     /**
451      * Test size bug, used to blow up if size was called before any queries.
452      */

453     public void testSize() {
454         String JavaDoc rules = "[rule1: (?x p ?y) -> (?x q ?y)]";
455         List ruleList = Rule.parseRules(rules);
456         Graph data = new GraphMem();
457         data.add(new Triple(n1, p, n2));
458         InfGraph infgraph = new BasicForwardRuleReasoner(ruleList).bind(data);
459         assertEquals(infgraph.size(), 2);
460     }
461     
462     /**
463      * Check validity report implementation, there had been a stupid bug here.
464      */

465     public void testValidityReport() {
466         StandardValidityReport report = new StandardValidityReport();
467         report.add(false, "dummy", "dummy1");
468         report.add(false, "dummy", "dummy3");
469         assertTrue(report.isValid());
470         report.add(true, "dummy", "dummy2");
471         assertTrue( ! report.isValid());
472         
473         report = new StandardValidityReport();
474         report.add(false, "dummy", "dummy1");
475         report.add(true, "dummy", "dummy2");
476         report.add(false, "dummy", "dummy3");
477         assertTrue( ! report.isValid());
478
479         report = new StandardValidityReport();
480         report.add(new ValidityReport.Report(false, "dummy", "dummy1"));
481         report.add(new ValidityReport.Report(true, "dummy", "dummy2"));
482         report.add(new ValidityReport.Report(false, "dummy", "dummy3"));
483         assertTrue( ! report.isValid());
484     }
485        
486     /**
487      * Test the list conversion utility that is used in some of the builtins.
488      */

489     public void testConvertList() {
490         Graph data = new GraphMem();
491         Node first = RDF.Nodes.first;
492         Node rest = RDF.Nodes.rest;
493         Node nil = RDF.Nodes.nil;
494         data.add(new Triple(n1, first, p));
495         data.add(new Triple(n1, rest, n2));
496         data.add(new Triple(n2, first, q));
497         data.add(new Triple(n2, rest, nil));
498
499         data.add(new Triple(n3, first, p));
500         data.add(new Triple(n3, rest, n4));
501         data.add(new Triple(n4, rest, n5));
502         data.add(new Triple(n5, first, q));
503         data.add(new Triple(n5, rest, nil));
504         
505         String JavaDoc rules = "[rule1: (?x p ?y) -> (?x q ?y)]";
506         List ruleList = Rule.parseRules(rules);
507         InfGraph infgraph = new BasicForwardRuleReasoner(ruleList).bind(data);
508         
509         RuleContext context = new BFRuleContext( (ForwardRuleInfGraphI) infgraph);
510         List result = Util.convertList(n1, context);
511         assertEquals(result.size(), 2);
512         assertEquals(result.get(0), p);
513         assertEquals(result.get(1), q);
514
515         List result2 = Util.convertList(n3, context);
516         assertEquals(result2.size(), 1);
517         assertEquals(result2.get(0), p);
518     }
519      
520 }
521
522 /*
523     (c) Copyright 2003, 2004, 2005 Hewlett-Packard Development Company, LP
524     All rights reserved.
525
526     Redistribution and use in source and binary forms, with or without
527     modification, are permitted provided that the following conditions
528     are met:
529
530     1. Redistributions of source code must retain the above copyright
531        notice, this list of conditions and the following disclaimer.
532
533     2. Redistributions in binary form must reproduce the above copyright
534        notice, this list of conditions and the following disclaimer in the
535        documentation and/or other materials provided with the distribution.
536
537     3. The name of the author may not be used to endorse or promote products
538        derived from this software without specific prior written permission.
539
540     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
541     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
542     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
543     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
544     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
545     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
546     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
547     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
548     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
549     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
550 */

551
552
Popular Tags