KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > hp > hpl > jena > ontology > daml > impl > test > DAMLTest


1 /*****************************************************************************
2  * Source code information
3  * -----------------------
4  * Original author Ian Dickinson, HP Labs Bristol
5  * Author email Ian.Dickinson@hp.com
6  * Package Jena
7  * Created 10 Nov 2000
8  * Filename $RCSfile: DAMLTest.java,v $
9  * Revision $Revision: 1.28 $
10  * Release status Preview-release $State: Exp $
11  *
12  * Last modified on $Date: 2005/04/08 17:37:12 $
13  * by $Author: ian_dickinson $
14  *
15  * (c) Copyright 2001, 2002, 2003, 2004, 2005 Hewlett-Packard Development Company, LP
16  * (see footer for full conditions)
17  *****************************************************************************/

18
19 // Package
20
///////////////
21
package com.hp.hpl.jena.ontology.daml.impl.test;
22
23
24 // Imports
25
///////////////
26
import junit.framework.*;
27
28 import com.hp.hpl.jena.rdf.model.*;
29 import com.hp.hpl.jena.datatypes.TypeMapper;
30 import com.hp.hpl.jena.ontology.OntDocumentManager;
31 import com.hp.hpl.jena.ontology.daml.*;
32 import com.hp.hpl.jena.vocabulary.*;
33
34 import java.util.*;
35
36 import java.io.*;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40
41
42 /**
43  * Legacy JUnit regression tests for the Jena DAML model.
44  *
45  * @author Ian Dickinson, HP Labs (<a HREF="mailto:Ian.Dickinson@hp.com">email</a>)
46  * @version CVS info: $Id: DAMLTest.java,v 1.28 2005/04/08 17:37:12 ian_dickinson Exp $,
47  */

48 public class DAMLTest
49     extends TestCase
50 {
51     // Constants
52
//////////////////////////////////
53

54
55     // Static variables
56
//////////////////////////////////
57

58     private static Log log = LogFactory.getLog( DAMLTest.class );
59
60
61     // Instance variables
62
//////////////////////////////////
63

64     // Constructors
65
//////////////////////////////////
66

67     /**
68      * Constructor requires that all tests be named
69      *
70      * @param name The name of this test
71      */

72     public DAMLTest( String JavaDoc name ) {
73         super( name );
74     }
75
76
77
78     // External signature methods
79
//////////////////////////////////
80

81
82
83     // Internal implementation methods
84
//////////////////////////////////
85

86     /**
87      * Set up the test conditions
88      */

89     public void setUp() {
90         // reset default condition
91
OntDocumentManager.getInstance().reset( true );
92     }
93
94
95     /**
96      * Release objects no longer needede when we're done
97      */

98     public void tearDown() {
99     }
100
101
102     // Test cases
103
/////////////
104

105     /**
106      * Test the various pathways through loading the ontology from a source document.
107      */

108     public void testLoadOntology()
109
110     {
111         DAMLModel m = getCleanModel();
112
113         // first do the model read with all options turned on
114
m.read( "file:testing/ontology/daml/daml_oil_2001_03/daml+oil-ex.daml", "http://www.daml.org/2001/03/daml+oil-ex", null );
115         assertTrue( "Load success status should be true", m.getLoadSuccessful() );
116         assertEquals( "Count of number of classes in daml store (2001/03, import)", 31, countClasses( m ) );
117         // Replaced by der after reasoner update, uncertain whether the "new" results are correct yet!
118
// assertEquals( "Property count ", 66, countProperties( m ) );
119
assertEquals( "Property count ", 68, countProperties( m ) );
120         //dumpModel( m );
121

122         // now turn off importing - should only get the classes and properties in the source doc
123
m = getCleanModel();
124         m.getLoader().setLoadImportedOntologies( false );
125         m.read( "file:testing/ontology/daml/daml_oil_2001_03/daml+oil-ex.daml", "http://www.daml.org/2001/03/daml+oil-ex", null );
126         assertTrue( "Load success status should be true", m.getLoadSuccessful() );
127         assertEquals( "Count of number of classes in daml store (2001/03, no import)", 16, countClasses( m ) );
128
129         // test case for bug reported by Charlie Abela: must be able to load instance files that import
130
// their own class declarations
131
m = getCleanModel();
132         m.read( "file:testing/ontology/daml/test-instance-load.daml" );
133         assertTrue( "Load status should be true", m.getLoadSuccessful() );
134         Resource pugh = m.getResource( "http://dickinson-i-4/daml/tests/test-instance-load.daml#pugh" );
135         assertNotNull( "Resource for officer Pugh should not be null", pugh );
136         DAMLInstance pughInst = (DAMLInstance) pugh.as( DAMLInstance.class );
137         assertNotNull( pughInst );
138
139         // test case for bug report by Michael Sintek
140
// try to ascertain the most specific class we can at load time -
141
// case in point is shoesize in standard example ontology
142
m = getCleanModel();
143         m.read( "file:testing/ontology/daml/daml_oil_2001_03/daml+oil-ex.daml", "http://www.daml.org/2001/03/daml+oil-ex", null );
144         assertTrue( "Load success status should be true", m.getLoadSuccessful() );
145         DAMLProperty shoesize = (DAMLProperty) m.getProperty( "http://www.daml.org/2001/03/daml+oil-ex#shoesize" ).as( DAMLProperty.class );
146         assertNotNull( "Failed to find shoesize property in example ontology", shoesize );
147         assertEquals( "shoesize should be a unique property", true, shoesize.isUnique() );
148     }
149
150
151     /**
152      * Test case for testing rdf:type traversal
153      */

154     public void testRDFType()
155
156     {
157         String JavaDoc ns = "http://dickinson-i-4/daml/tests/test-cases.daml#";
158
159         DAMLModel m = getCleanModel();
160         m.read( "file:testing/ontology/daml/test-cases.daml" );
161
162         //dumpModel( m );
163

164         // first find fido
165
DAMLInstance fido = m.getDAMLInstance( ns + "fido" );
166         assertNotNull( "fido instance should not be null", fido );
167
168         // lookup some classes for convenience
169
DAMLClass cDog = m.getDAMLClass( ns + "Dog" );
170         assertNotNull( "Dog class should not be null", cDog );
171
172         DAMLClass cVertebrate = m.getDAMLClass( ns + "Vertebrate" );
173         assertNotNull( "Vertebrate class should not be null", cVertebrate );
174
175         DAMLClass cPet = m.getDAMLClass( ns + "Pet" );
176         assertNotNull( "Pet class should not be null", cPet );
177
178         // fido is a Dog, a vertebrate and a pet
179
assertTrue( "fido should be member of class Dog", fido.hasRDFType( cDog ) );
180         assertTrue( "fido should be member of class Vertebrate", fido.hasRDFType( cVertebrate ) );
181         assertTrue( "fido should be member of class Vertebrate (by URL)", fido.hasRDFType( ns + "Vertebrate" ) );
182         assertTrue( "fido should be member of class Pet", fido.hasRDFType( cPet ) );
183
184         // fido is not a class
185
assertTrue( "fido should not be a class", !fido.hasRDFType( DAML_OIL.Class ) );
186
187         // fido is a companion, even though this class is not defined in the current ontology
188
assertTrue( "fido should be a companion", fido.hasRDFType( ns + "Companion" ) );
189
190         // fido is a Thing (all things DAML are Things)
191
// disabled pending adding DAML semantic rules assertTrue( "fido should be a thing", fido.hasRDFType( DAML_OIL.Thing ) );
192

193         // get some more classes
194
DAMLClass cA = m.getDAMLClass( ns + "A" );
195         assertNotNull( "Class A should not be null", cA );
196
197         DAMLClass cB = m.getDAMLClass( ns + "B" );
198         assertNotNull( "Class B should not be null", cB );
199
200         DAMLInstance ab = m.getDAMLInstance( ns + "ab" );
201         assertNotNull( "Instance ab should not be null", ab );
202
203         // note that cA --subclass--> cB --subclass--> cA is a loop
204
assertTrue( "ab should be an A", ab.hasRDFType( cA ) );
205         assertTrue( "ab should be a B", ab.hasRDFType( cB ) );
206
207         // how many ways do I know thee? let me count the ways ...
208
assertEquals( "Number of classes fido belongs to (closure) should be 8",
209                       8, countIteration( fido.getRDFTypes( true ), true, "fido member of class " ) );
210         assertEquals( "Number of classes fido belongs to (non-closure) should be 3",
211                       3, countIteration( fido.getRDFTypes( false ), true, "fido member of non-closed class " ) );
212
213         // some tests on the built-in classes
214
DAMLProperty queenOf = m.getDAMLProperty( ns + "queen-of" );
215         assertNotNull( "queen-of property should be defined", queenOf );
216         assertTrue( "an UnabmbiguousProperty should be an ObjectProperty", queenOf.hasRDFType( DAML_OIL.UnambiguousProperty ) );
217         assertTrue( "an UnabmbiguousProperty should be an ObjectProperty", queenOf.hasRDFType( DAML_OIL.ObjectProperty ) );
218         assertTrue( "an UnabmbiguousProperty should be an rdf:Property", queenOf.hasRDFType( RDF.Property ) );
219     }
220
221
222     /**
223      * Test some of the properties of DAML classes
224      */

225     public void testClass() {
226         DAMLModel m = getCleanModel();
227
228         m.read( "file:testing/ontology/daml/daml_oil_2001_03/daml+oil-ex.daml", "http://www.daml.org/2001/03/daml+oil-ex", null );
229         assertTrue( "loadStatus should be true for successful load", m.getLoadSuccessful() );
230         String JavaDoc ns = "http://www.daml.org/2001/03/daml+oil-ex#";
231
232         // get a reference to the Person class
233
DAMLClass person = m.getDAMLClass( ns + "Person" );
234         assertNotNull( "Person class should not be null", person );
235         assertTrue( "Person should be a named class", person.isNamedClass() );
236
237         // count the super-classes of a Person
238
int sCount0 = countIteration( person.prop_subClassOf().getAll( ), true, "super-class of Person (prop_subClassOf) " );
239         int sCount1 = countIteration( person.getSuperClasses(), true, "super-class of Person (getSuperClasses) " );
240         assertEquals( "person should have 10 super-classes (by prop_subClassOf)", 10, sCount0 );
241         assertEquals( "person should have 9 super-classes (by getSuperClasses)", 9, sCount1 );
242
243         // count the number of sub-classes of a Person
244
assertEquals( "person should have 3 sub-classes", 3,
245                       countIteration( person.getSubClasses(), true, "Person super-class of: " ) );
246
247         // person is a disjoint union of Man and Woman
248
assertTrue( "Person should be a disjoint union", person.isDisjointUnion() );
249         DAMLList mw = person.prop_disjointUnionOf().getList();
250         assertNotNull( "Value of disjoint union should not be null", mw );
251         assertEquals( "Person should be a disjoint union of size 2", 2, mw.getCount() );
252
253         // Female is disjoint with Male
254
DAMLClass female = m.getDAMLClass( ns + "Female" );
255         assertNotNull( "Class Female should not be null", female );
256         DAMLClass male = m.getDAMLClass( ns + "Male" );
257         assertNotNull( "Class Male should not be null", male );
258         assertTrue( "Female should be disjoint with male", female.prop_disjointWith().hasValue( male ) );
259
260         // HumanBeing is the same class as Person
261
DAMLClass humanBeing = m.getDAMLClass( ns + "HumanBeing" );
262         assertNotNull( "Class humanBeing should not be null", humanBeing );
263         assertTrue( "Person should be same class as HumanBeing", humanBeing.prop_sameClassAs().hasValue( person ) );
264
265         // TallMan is an intersection of Man and TallThing
266
DAMLClass tallMan = m.getDAMLClass( ns + "TallMan" );
267         assertNotNull( "Class TallMan should not be null", tallMan );
268         DAMLList tm = tallMan.prop_intersectionOf().getList();
269         assertNotNull( "Value of intersection should not be null", tm );
270         assertEquals( "Tall man should be an intersection of size 2", 2, tm.getCount() );
271
272         // Car is a complement of Person
273
DAMLClass car = m.getDAMLClass( ns + "Car" );
274         assertNotNull( "Class Car should not be null", car );
275         DAMLClass carSuper = (DAMLClass) car.getSuperClasses(false).next();
276         assertNotNull( "Car should have a super-class", carSuper );
277         assertTrue( "Car super-class should be a complement", carSuper.isComplement() );
278         assertTrue( "Car super-class should be a complement of Person", carSuper.prop_complementOf().hasValue( person ) );
279
280         // Height is an enumeration of three values
281
DAMLClass height = m.getDAMLClass( ns + "Height" );
282         assertNotNull( "Class Height should not be null", height );
283         assertTrue( "Height should be an enumeration", height.isEnumeration() );
284         assertEquals( "Height should be an enumeration of 3 elements", 3, height.prop_oneOf().getList().getCount() );
285
286         // daml:subClassOf is processed as rdfs:subClassOf
287
DAMLModel m0 = getCleanModel();
288         m0.getLoader().setLoadImportedOntologies( true );
289         m0.read( "file:testing/ontology/daml/test-cases.daml", "http://dickinson-i-4/daml/tests/test-cases.daml", null );
290         String JavaDoc tcNs = "http://dickinson-i-4/daml/tests/test-cases.daml#";
291         DAMLClass subClassBug0 = m0.getDAMLClass( tcNs + "SubClassBug0" );
292         DAMLClass subClassBug1 = m0.getDAMLClass( tcNs + "SubClassBug1" );
293         assertNotNull( "Class SubClassBug0 should not be null", subClassBug0 );
294         assertNotNull( "Class SubClassBug1 should not be null", subClassBug1 );
295         assertTrue( "SubClassBug1 should have SubClassBug0 as a super-class", subClassBug1.hasSuperClass( subClassBug0 ) );
296         assertTrue( "SubClassBug0 should have SubClassBug1 as a sub-class", subClassBug0.hasSubClass( subClassBug1 ) );
297
298         // defined properties are those that mention this class as domain
299
DAMLClass defProp0 = m0.getDAMLClass( tcNs + "DefProp0" );
300         DAMLClass defProp1 = m0.getDAMLClass( tcNs + "DefProp1" );
301         DAMLClass defProp2 = m0.getDAMLClass( tcNs + "DefProp2" );
302         assertNotNull( "Class DefProp0 should not be null", defProp0 );
303         assertNotNull( "Class DefProp1 should not be null", defProp1 );
304         assertNotNull( "Class DefProp2 should not be null", defProp2 );
305
306         int nP0 = countIteration( defProp0.getDefinedProperties(), true, "Defined property of DefProp0, closed" );
307         int nP0nc = countIteration( defProp0.getDefinedProperties( false ), true, "Defined property of DefProp0, not closed" );
308         int nP1 = countIteration( defProp1.getDefinedProperties(), true, "Defined property of DefProp1, closed" );
309         int nP1nc = countIteration( defProp1.getDefinedProperties( false ), true, "Defined property of DefProp1, not closed" );
310         int nP2 = countIteration( defProp2.getDefinedProperties(), true, "Defined property of DefProp2, closed" );
311         int nP2nc = countIteration( defProp2.getDefinedProperties( false ), true, "Defined property of DefProp2, not closed" );
312         assertEquals( "Defined properties of DefProp0 should number 11", 11, nP0 );
313         assertEquals( "Defined properties of DefProp0 (non-closed) should number 11", 11, nP0nc );
314         assertEquals( "Defined properties of DefProp1 should number 11", 11, nP1 );
315         assertEquals( "Defined properties of DefProp1 (non-closed) should number 0", 0, nP1nc );
316
317         assertEquals( "Defined properties of DefProp2 should number 12", 12, nP2 );
318         assertEquals( "Defined properties of DefProp2 (non-closed) should number 1", 1, nP2nc );
319         assertEquals( "Defined properties of DefProp2 should number 12", 12, nP2 );
320         assertEquals( "Defined properties of DefProp2 (non-closed) should number 1", 1, nP2nc );
321
322         // Bug report by Thorsten Liebig
323
DAMLClass tl_one = m0.getDAMLClass( tcNs + "tl_one" );
324         assertNotNull( "Class tl_one should not be null", tl_one );
325         int tl_one_supers0 = countIteration( tl_one.prop_subClassOf().getAll( ), true, "prop_subClassOf " );
326         int tl_one_supers1 = countIteration( tl_one.getSuperClasses( false ), true, "getSuperClasses ");
327         assertEquals( "Should be four super-classes of tl_one by prop_subClassOf", 4, tl_one_supers0 );
328         assertEquals( "Should be two super-classes of tl_one by getSuperClasses", 2, tl_one_supers1 );
329
330         // Bug report by Andrei S. Lopatenko
331
DAMLClass researcher = m0.getDAMLClass( tcNs + "Researcher" );
332         assertNotNull( "Class Researcher should not be null", researcher );
333         int researcherSupers = countIteration( researcher.getSuperClasses( false ), true, "Super-class of researcher" );
334         assertEquals( "Should be 2 super-classes of researcher", 2, researcherSupers );
335     }
336
337
338     /**
339      * Test equivalance classes
340      */

341     public void testEquivalence() {
342         String JavaDoc ns = "http://dickinson-i-4/daml/tests/test-cases.daml#";
343
344         DAMLModel m = getCleanModel();
345
346         // don't allow any additional info to load
347
m.read( "file:testing/ontology/daml/test-cases.daml", "http://dickinson-i-4/daml/tests/test-cases.daml", null );
348
349         // get the root object
350
DAMLInstance root = m.getDAMLInstance( ns + "x0" );
351         assertNotNull( "Instance x0 should not be null", root );
352         // should really be 4 under daml rules, but only 1 under rdfs with no support for daml entailments
353
assertEquals( "Number of elements in equivalence class should be 1", 1,
354                       countIteration( root.getEquivalentValues(), true, "Member of equivalence class to x0: " ) );
355
356         // now it's the classes' turn ...
357
DAMLClass cRoot = m.getDAMLClass( ns + "C0" );
358         assertNotNull( "Class C0 should not be null", cRoot );
359         // should be 4 under daml semantic rules, but only 1 under rdfs
360
assertEquals( "Number of elements in equivalence class should be 1", 1,
361                       countIteration( cRoot.getSameClasses(), true, "sameClass as C0: " ) );
362
363         // and now the properties ...
364
DAMLProperty pRoot = m.getDAMLProperty( ns + "p0" );
365         assertNotNull( "Property p0 should not be null", pRoot );
366         // should be 4 under daml semantics rules, but only 1 under rdfs
367
assertEquals( "Number of elements in equivalence class should be 1", 1,
368                       countIteration( pRoot.getSameProperties(), true, "sameProperty as p0: " ) );
369
370         // check that daml:type is recognised as equivalent to rdf:type
371
Resource dClass = m.getResource( ns + "CDaml" );
372         assertNotNull( "Resource dClass should not be null", dClass );
373         assertTrue( "Resource dClass should be a daml class", dClass.canAs( DAMLClass.class ) );
374
375         // check that class equivalence is considered during type testing
376
DAMLClass cD0 = m.getDAMLClass( ns + "D0" );
377         DAMLClass cD1 = m.getDAMLClass( ns + "D1" );
378         DAMLInstance d1 = m.getDAMLInstance( ns + "d1" );
379         assertNotNull( "Class D0 should not be null", cD0 );
380         assertNotNull( "Class D1 should not be null", cD1 );
381         assertNotNull( "Instance d1 should not be null", d1 );
382
383         assertTrue( "Instance d1 should have class D1", d1.hasRDFType( cD1 ) );
384         // RDFS reasoner can't do class equivalence assertTrue( "Instance d1 should have class D0", d1.hasRDFType( cD0 ) );
385

386         // check equivalence on properties, pd0 and pd1 are the same
387
DAMLProperty pd0 = m.getDAMLProperty( ns + "pd0" );
388         DAMLProperty pd1 = m.getDAMLProperty( ns + "pd1" );
389         assertNotNull( "Property pd0 should not be null", pd0 );
390         assertNotNull( "Property pd1 should not be null", pd1 );
391
392         DAMLInstance d2 = m.getDAMLInstance( ns + "d2" );
393         assertNotNull( "Instance d2 should not be null", d2 );
394
395         // check that d2 has d1 as a property value under pd0, and pd1 (it's equivalent)
396
assertTrue( "d2 should have d1 as a value for pd0", d2.accessProperty( pd0 ).hasValue( d1 ) );
397         // RDFS reasoner can't do property equivalence assertTrue( "d2 should have d1 as a value for pd1", d2.accessProperty( pd1 ).hasValue( d1 ) );
398

399         DAMLProperty pd2 = m.getDAMLProperty( ns + "pd2" );
400         DAMLProperty pd3 = m.getDAMLProperty( ns + "pd3" );
401         assertNotNull( "Property pd2 should not be null", pd2 );
402         assertNotNull( "Property pd3 should not be null", pd3 );
403
404         // we know that 'd1 pd3 d2', which implies 'd1 pd2 d2' since pd2 is a super-prop of pd3
405
assertTrue( "d2 should have d1 as a value for pd3", d2.accessProperty( pd3 ).hasValue( d1 ) );
406         assertTrue( "d2 should have d1 as a value for pd2", d2.accessProperty( pd2 ).hasValue( d1 ) );
407     }
408
409
410     /**
411      * Unit tests on DAMLProperty and its subclasses
412      */

413     public void testProperty() {
414         DAMLModel m = getCleanModel();
415
416         m.read( "file:testing/ontology/daml/daml_oil_2001_03/daml+oil-ex.daml", "http://www.daml.org/2001/03/daml+oil-ex", null );
417         assertTrue( "loadStatus should be true for successful load", m.getLoadSuccessful() );
418         String JavaDoc ns = "http://www.daml.org/2001/03/daml+oil-ex#";
419
420         // Tests on property objects themselves
421
DAMLProperty hasMother = m.getDAMLProperty( ns + "hasMother" );
422         assertNotNull( "hasMother property should not be null", hasMother );
423         assertTrue( "hasMother property should be a unique property", hasMother.isUnique() );
424
425         DAMLProperty hasParent = m.getDAMLProperty( ns + "hasParent" );
426         assertNotNull( "hasParent property should not be null", hasParent );
427
428         DAMLClass female = m.getDAMLClass( ns + "Female" );
429         assertNotNull( "Class Female should not be null", female );
430         DAMLClass animal = m.getDAMLClass( ns + "Animal" );
431         assertNotNull( "Class Animal should not be null", animal );
432         DAMLClass person = m.getDAMLClass( ns + "Person" );
433         assertNotNull( "Class Person should not be null", person );
434
435         // range of hasMother includes female
436
assertTrue( "Mother should have Female as range", hasMother.prop_range().hasValue( female ) );
437         assertTrue( "Mother should not have Animal as local domain (prop_domain)", !hasMother.prop_domain().hasValue( animal ) );
438
439         /* test removed - depends on reasoner configuration
440         boolean found = false;
441         for (Iterator i = hasMother.getDomainClasses(); !found && i.hasNext(); ) {
442             Object cls = i.next();
443             found = found || cls.equals( animal );
444         }
445         assertTrue( "Mother should have Animal as domain (getDomainClasses)", found );
446         */

447
448         // ancestor is transitive
449
DAMLObjectProperty hasAncestor = (DAMLObjectProperty) m.getDAMLProperty( ns + "hasAncestor" ).as( DAMLObjectProperty.class );
450         assertNotNull( "hasAncestor should not be null", hasAncestor );
451         assertTrue( "hasAncestor should be transitive", hasAncestor.isTransitive() );
452
453         // bug report by Michael Sintek: getNext() does not terminate on getAll(false)
454
DAMLInstance peter = m.getDAMLInstance( ns + "Peter" );
455         assertNotNull( "Instance Peter should not be null", peter );
456         DAMLProperty shoesize = m.getDAMLProperty( ns + "shoesize" );
457         assertNotNull( "Property shoesize should not be null", shoesize );
458         PropertyAccessor paShoesize = peter.accessProperty( shoesize );
459         Iterator iShoes = paShoesize.getAll( );
460         assertEquals( "iShoes iterator should have at least one value", true, iShoes.hasNext() );
461         Object JavaDoc size = iShoes.next();
462         assertNotNull( "size returned from property accessor iterator should not be null", size );
463         assertTrue( "size object should be a literal", size instanceof Literal );
464         boolean nse = false;
465         try {
466             iShoes.next();
467         }
468         catch (NoSuchElementException ignore) {
469             nse = true;
470         }
471         assertEquals( "Accessing past end of property iterator should throw no such element exception", true, nse );
472
473         // try the same bug test with a multi-valued property
474
Iterator iSubClassOf = person.prop_subClassOf().getAll( );
475         assertNotNull( "Iterator over subClassOf values should not be null", iSubClassOf );
476         assertTrue( "Iteration of subClassOf should have at least one value", iSubClassOf.hasNext() );
477         int nSupers = countIteration( iSubClassOf, true, "direct super-class of Person = " );
478         assertEquals( "Should be 10 super-classes of Person", 10, nSupers );
479
480         // another bug report from Michael Sintek - get() on single-valued property does not terminate
481
DAMLClass male = m.getDAMLClass( ns + "Male" );
482         assertNotNull( "Class Male should not be null", male );
483         DAMLCommon femaleDisjoint = (DAMLCommon) female.prop_disjointWith().get();
484         assertNotNull( "Value for female.disjointWith should not be null", femaleDisjoint );
485         assertTrue( "female.disjointWith should be male", male.equals( femaleDisjoint ) );
486
487         // another property accessor check
488
m.getLoader().setLoadImportedOntologies( false );
489         m.read( "file:testing/ontology/daml/test-cases.daml", "http://dickinson-i-4/daml/tests/test-cases.daml", null );
490         assertTrue( "loadStatus should be true for successful load", m.getLoadSuccessful() );
491         ns = "http://dickinson-i-4/daml/tests/test-cases.daml#";
492
493         DAMLClass subClassCheck3 = (DAMLClass) m.getDAMLValue( ns + "subClassCheck3" ).as( DAMLClass.class );
494         assertNotNull( "Class subClassCheck3 should not be null", subClassCheck3 );
495
496         Iterator iSubClassOf3 = subClassCheck3.getSuperClasses( false ); // not closed
497
assertNotNull( "Iterator over subClassOf values should not be null", iSubClassOf );
498         assertTrue( "Iteration of subClassOf should have at least one value", iSubClassOf3.hasNext() );
499         nSupers = countIteration( iSubClassOf3, true, "property access on subClassCheck3" );
500         assertEquals( "Should be 1 non-closed super-classes of subClassCheck3", 1, nSupers );
501
502         iSubClassOf3 = subClassCheck3.getSuperClasses( true ); // closed
503
assertNotNull( "Iterator over subClassOf values should not be null", iSubClassOf );
504         assertTrue( "Iteration of subClassOf should have at least one value", iSubClassOf3.hasNext() );
505         nSupers = countIteration( iSubClassOf3, true, "property access on subClassCheck3 with closed = true " );
506         assertEquals( "Should be 3 closed super-classes of subClassCheck3", 3, nSupers );
507
508         // bug submitted by Michael Sintek: setUseEquivalence(false) does not work with property accessors
509
DAMLProperty q = m.getDAMLProperty( ns + "q" );
510         assertNotNull( "Property q should not be null", q );
511         DAMLInstance qX = m.getDAMLInstance( ns + "qX" );
512         assertNotNull( "Instance qX should not be null", qX );
513
514         // with equivalence turned on, there should be four values for q of qX
515
int nQ = qX.accessProperty( q ).count();
516         // daml equivalance not currently implemented assertEquals( "There should be 4 values for q of qX (equivalence on)", 4, nQ );
517

518         // turn off equivalence, should only be one value
519
assertEquals( "There should be 1 values for q of qX (equivalence off)", 1, nQ );
520
521         // Bug report by Thorsten Liebig
522
DAMLProperty tlPropTest = (DAMLObjectProperty) m.getDAMLProperty( ns + "TL_PropertyTest" ).as( DAMLObjectProperty.class );
523         assertNotNull( "Property should not be null", tlPropTest );
524
525         Iterator tl_domains = tlPropTest.prop_domain().getAll();
526         assertEquals( "Property TL_PropertyTest should have a domain of two classes", 2, countIteration( tl_domains, false, null ) );
527         Iterator tl_ranges = tlPropTest.prop_range().getAll();
528         assertEquals( "Property TL_PropertyTest should have a range of two classes", 2, countIteration( tl_ranges, false, null ) );
529
530         // bug reported by Wesley Bille
531
DAMLClass humanBody = (DAMLClass) m.getDAMLValue( ns + "HumanBody" ).as( DAMLClass.class );
532         assertNotNull( "Class humanBody should not be null", humanBody );
533         PropertyAccessor propUnion = humanBody.prop_unionOf();
534         assertNotNull( "Property accessor should not be null", propUnion );
535         assertEquals( "Should be two value in union", 1, propUnion.count() );
536         DAMLCommon union = propUnion.getDAMLValue();
537         assertNotNull( "Union should not be null", union );
538         assertTrue( "Union value should be a list", union.canAs( DAMLList.class ) );
539         assertEquals( "Should be two values in list", 2, ((DAMLList) union.as( DAMLList.class )).getCount() );
540     }
541
542
543     /**
544      * Tests on lists
545      */

546     public void testList() {
547         DAMLModel m = getCleanModel();
548
549         m.read( "file:testing/ontology/daml/daml_oil_2001_03/daml+oil-ex.daml", "http://www.daml.org/2001/03/daml+oil-ex", null );
550         assertTrue( "loadStatus should be true for successful load", m.getLoadSuccessful() );
551         String JavaDoc ns = "http://www.daml.org/2001/03/daml+oil-ex#";
552
553         // get the Person class
554
DAMLClass person = m.getDAMLClass( ns + "Person" );
555         assertNotNull( "Person class should not be null", person );
556         DAMLClass man = m.getDAMLClass( ns + "Man" );
557         assertNotNull( "Man class should not be null", man );
558         DAMLClass woman = m.getDAMLClass( ns + "Woman" );
559         assertNotNull( "Woman class should not be null", woman );
560
561         // check some basic characteristics of the list
562
DAMLList union = (DAMLList) person.prop_disjointUnionOf().get().as( DAMLList.class );
563         assertNotNull( "union should not be null", union );
564         assertEquals( "union should have two values", 2, union.getCount() );
565
566         // man should be the first element in the list
567
RDFNode val1 = union.getFirst();
568         assertEquals( "Man should be the first element in the list", man, val1 );
569
570         // woman should be the other element in the list
571
DAMLList tail = union.getRest();
572         assertNotNull( "Tail of list should not be null", tail );
573
574         RDFNode val2 = tail.getFirst();
575         assertNotNull( "head of tail should not be null", val2 );
576         assertEquals( "Woman should be the first element in the tail of the list", woman, val2 );
577
578         DAMLList tail2 = tail.getRest();
579         assertNotNull( "Tail of tail should not be null", tail2 );
580         assertTrue( "Remainder of list should be empty", tail2.isEmpty() );
581
582         // ontologically nonsensical ... just want to test list manipulations
583
DAMLClass car = m.getDAMLClass( ns + "Car" );
584         assertNotNull( "Class Car should not be null", car );
585         union.add( car );
586         // DEBUG dumpModel( m.getModel() );
587
assertEquals( "Union should contain three elements", 3, union.getCount() );
588     }
589
590
591     /**
592      * Tests on instances
593      */

594     public void testInstance() {
595         DAMLModel m = getCleanModel();
596
597         m.read( "file:testing/ontology/daml/daml_oil_2001_03/daml+oil-ex.daml", "http://www.daml.org/2001/03/daml+oil-ex", null );
598         assertTrue( "loadStatus should be true for successful load", m.getLoadSuccessful() );
599         String JavaDoc ns = "http://www.daml.org/2001/03/daml+oil-ex#";
600
601         // count the number of instances loaded from the standard example
602
assertEquals( "Number of instances should be 7", 7,
603                       countIteration( m.listDAMLInstances(), false, " instance = " ) );
604
605         // test listing the instances of a class
606
DAMLClass person = m.getDAMLClass( ns + "Person" );
607         assertNotNull( "Person DAML class should not be null", person );
608         int nPerson = countIteration( person.getInstances(), true, "instance of person" );
609         assertEquals( "There should be 4 instances of Person in the model", 4, nPerson );
610     }
611
612
613     /**
614      * Tests on DAML datatypes
615      */

616     public void testDatatype() {
617         DAMLModel m = getCleanModel();
618
619         m.read( "file:testing/ontology/daml/daml_oil_2001_03/daml+oil-ex.daml", "http://www.daml.org/2001/03/daml+oil-ex", null );
620         assertTrue( "loadStatus should be true for successful load", m.getLoadSuccessful() );
621         String JavaDoc ns = "http://www.daml.org/2001/03/daml+oil-ex#";
622
623         // get the Person class
624
DAMLInstance ian = m.getDAMLInstance( ns + "Ian" );
625         assertNotNull( "Instance Ian should not be null", ian );
626         DAMLProperty shirtsize = m.getDAMLProperty( ns + "shirtsize" );
627         assertNotNull( "Property shirtsize should not be null", shirtsize );
628         DAMLProperty shoesize = m.getDAMLProperty( ns + "shoesize" );
629         assertNotNull( "Property shoesize should not be null", shoesize );
630
631         DAMLDataInstance sSize = (DAMLDataInstance) ian.getRequiredProperty( shirtsize ).getObject().as( DAMLDataInstance.class );
632         assertNotNull( "Object ian should have a shirtsize", sSize );
633         Object JavaDoc x = sSize.getValue();
634         assertNotNull( "Value of shirtsize should not be null", x );
635         assertEquals( "Shirt size should be a string", String JavaDoc.class, x.getClass() );
636         assertEquals( "Shirt size should be \"12\"", "12", x );
637     }
638
639
640     public void testDataInstance() {
641         DAMLModel m = getCleanModel();
642         DAMLDataInstance di = m.createDAMLDataInstance( new Integer JavaDoc( 9 ) );
643         assertNotNull( "Failed to create data instance ", di );
644         assertEquals( "data instance URI not correct ", TypeMapper.getInstance().getTypeByName( XSD.xint.getURI() ), di.getDatatype() );
645
646         String JavaDoc NS="http://example.org/eg#";
647         DAMLClass person = m.createDAMLClass( NS+"Person");
648         DAMLInstance peter = m.createDAMLInstance( person, NS+"peter");
649         DAMLDatatypeProperty p = m.createDAMLDatatypeProperty( NS+"shirtsize");
650         peter.addProperty( p, di );
651
652         // just to confirm we are getting reasonable output m.write( System.out, "RDF/XML-ABBREV" );
653
}
654
655
656     /**
657      * Test the removal of DAML objects. We'll load a model, then
658      * delete everything in it one step at a time.
659      */

660     public void testRemove() {
661         DAMLModel m = ModelFactory.createDAMLModel();
662         m.getDocumentManager().setProcessImports( false );
663         m.read( "file:testing/ontology/daml/daml_oil_2001_03/daml+oil-ex.daml", "http://www.daml.org/2001/03/daml+oil-ex", null );
664         assertTrue( "loadStatus should be true for successful load", m.getLoadSuccessful() );
665
666         List cache = new ArrayList();
667         checkValidLists( m, "baseline" );
668
669         // remove classes, properties and instances
670
for (Iterator i = m.listDAMLClasses(); i.hasNext(); ) {
671             cache.add( i.next() );
672         }
673         while (!cache.isEmpty()) {
674             DAMLClass c = (DAMLClass) cache.remove( 0 );
675             log.debug( "Removing class " + c );
676             c.remove();
677             checkValidLists( m, "remove class" );
678         }
679
680         for (Iterator i = m.listDAMLInstances(); i.hasNext(); ) {
681             cache.add( i.next() );
682         }
683         while (!cache.isEmpty()) {
684             DAMLInstance c = (DAMLInstance) cache.remove( 0 );
685             log.debug( "Removing instance " + c );
686             c.remove();
687             checkValidLists( m, "remove instance" );
688         }
689
690         for (Iterator i = m.listDAMLProperties(); i.hasNext(); ) {
691             cache.add( i.next() );
692         }
693         while (!cache.isEmpty()) {
694             DAMLProperty c = (DAMLProperty) cache.remove( 0 );
695             log.debug( "Removing property " + c );
696             c.remove();
697             checkValidLists( m, "remove property" );
698         }
699
700         boolean notBuiltin = false;
701         for (Iterator i = m.listDAMLClasses(); i.hasNext(); ) {
702             Resource x = (Resource) i.next();
703             if (x.equals( DAML_OIL.Thing ) ||
704                 x.equals( DAML_OIL.Nothing ) ||
705                 x.hasProperty( DAML_OIL.complementOf, DAML_OIL.Nothing )) {
706                 // is a builtin
707
}
708             else {
709                 log.debug( "Unexpected class remains: " + x );
710                 for (StmtIterator j = ((Resource) x).listProperties(); j.hasNext(); ) {
711                     log.debug( " ... has prop " + j.next() );
712                 }
713                 notBuiltin = true;
714             }
715         }
716         assertFalse( "Should be no more classes", notBuiltin );
717         assertFalse( "Should be no more properties", m.listDAMLProperties().hasNext() );
718         assertFalse( "Should be no more instances", m.listDAMLInstances().hasNext() );
719     }
720
721
722     /**
723      * Test the creation of new DAML values
724      */

725     public void testCreate()
726
727     {
728         DAMLModel m = getCleanModel();
729
730         String JavaDoc cURI = "http://dickinson-i-4/daml/tests/gen#A";
731         DAMLClass c = m.createDAMLClass( cURI );
732         assertNotNull( "Failed to create new DAML Class " + cURI, c );
733
734         // check that we can find this class again
735
boolean found = false;
736         for (Iterator i = m.listDAMLClasses(); i.hasNext(); ) {
737             if (((DAMLClass) i.next()).equals( c )) {
738                 found = true;
739             }
740         }
741         assertTrue( "Could not see class after it was created", found );
742
743         // now create a new instance
744
DAMLInstance x = (DAMLInstance) m.createDAMLValue( "http://dickinson-i-4/daml/tests/gen#x", c );
745         assertNotNull( "Failed to create new DAML instance", x );
746
747         found = false;
748         for (Iterator i = m.listDAMLInstances(); i.hasNext(); ) {
749             if (((DAMLInstance) i.next()).equals( x )) {
750                 found = true;
751             }
752         }
753         assertTrue( "Could not see instance after it was created", found );
754     }
755
756
757
758     /**
759      * Testing restrictions
760      */

761     public void testRestriction() {
762         DAMLModel m = getCleanModel();
763
764         m.read( "file:testing/ontology/daml/daml_oil_2001_03/daml+oil-ex.daml", "http://www.daml.org/2001/03/daml+oil-ex", null );
765         assertTrue( "loadStatus should be true for successful load", m.getLoadSuccessful() );
766         String JavaDoc ns = "http://www.daml.org/2001/03/daml+oil-ex#";
767
768         // bug report by Michael Sintek: class cast exception from getting the value of the property iterator
769
// get a reference to the Person class
770
DAMLClass person = m.getDAMLClass( ns + "Person" );
771
772         // now get a restriction, which we can find as one of the super-classes of Person
773
for (Iterator i = person.getSuperClasses(); i.hasNext(); ) {
774             Resource r = (Resource) i.next();
775
776             if (r instanceof DAMLRestriction) {
777                 DAMLRestriction restriction = (DAMLRestriction) r;
778                 PropertyAccessor onPropertyAccessor = restriction.prop_onProperty();
779
780                 // now get the value from the restriction
781
int count = onPropertyAccessor.count();
782
783                 if (count >= 1) {
784                     Object JavaDoc x = onPropertyAccessor.get();
785                     Object JavaDoc y = onPropertyAccessor.getAll( ).next();
786
787                     assertNotNull( "Failed to access value of property accessor on restriction", x );
788                     assertNotNull( "Failed to access value of property accessor on restriction", y );
789                 }
790             }
791         }
792    }
793
794
795     /**
796      * Test adding a model to an existing model
797      */

798     public void testModelAdd() {
799         DAMLModel m = getCleanModel();
800
801         // create a daml model
802
m.read( "file:testing/ontology/daml/test-add-0.daml" );
803         assertTrue( "loadStatus should be true for successful load", m.getLoadSuccessful() );
804
805         // create a normal rdf model
806
Model m0 = ModelFactory.createDefaultModel();
807         m0.read( "file:testing/ontology/daml/test-add-1.daml" );
808
809         // should be 0 instances in the daml model so far
810
assertEquals( "Instance count in DAML model should be 0", 0, countIteration( m.listDAMLInstances(), true, "instance in test add" ) );
811
812         // now add the RDF data
813
m.add( m0 );
814
815         // now should be 1 instances in the daml model
816
assertEquals( "Instance count in DAML model should be 1", 1, countIteration( m.listDAMLInstances(), true, "instance in test add" ) );
817     }
818
819
820     /**
821      * Testing equality: case DatatypeProperty
822      */

823     public void testDatatypeProperty()
824
825     {
826         eqTest(new EqualityTest("DatatypeProperty") {
827                 String JavaDoc xml() {
828                     return "<daml:DatatypeProperty/>";
829                 }
830                 void java(DAMLModel m) {
831                     m.createDAMLDatatypeProperty(null);
832                 }
833         });
834     }
835     /**
836      * Testing equality: case ObjectProperty
837      */

838     public void testObjectProperty()
839
840     {
841         eqTest(new EqualityTest("ObjectProperty") {
842                 String JavaDoc xml() {
843                     return "<daml:ObjectProperty/>";
844                 }
845                 void java(DAMLModel m) {
846                     m.createDAMLObjectProperty(null);
847                 }
848         });
849     }
850     /**
851      * Testing equality: case Property
852      */

853     public void testPropertyEq()
854
855     {
856         eqTest(new EqualityTest("Property") {
857                 String JavaDoc xml() {
858                     return "<daml:Property/>";
859                 }
860                 void java(DAMLModel m) {
861                     m.createDAMLProperty(null);
862                 }
863         });
864     }
865
866
867     /**
868      * Testing equality: case Datatype
869      */

870     public void testDatatypeEq2()
871
872     {
873         eqTest(new EqualityTest("Datatype") {
874                 String JavaDoc xml() {
875                     return "<daml:Datatype rdf:about='http://www.w3.org/2000/10/XMLSchema#string'/>";
876                 }
877                 void java(DAMLModel m) {
878                     m.createDAMLDatatype("http://www.w3.org/2000/10/XMLSchema#string");
879                 }
880         });
881     }
882
883     public void testDatatypeRange()
884
885     {
886         eqTest(new EqualityTest("Datatype Range") {
887                 String JavaDoc xml() {
888                     // Example taken from the DAML+OIL walk-thru
889
return
890 "<daml:DatatypeProperty rdf:ID='shoesize'>"+
891  " <rdf:type rdf:resource='http://www.daml.org/2001/03/daml+oil#UniqueProperty'/>" +
892  " <daml:range rdf:resource='http://www.w3.org/2000/10/XMLSchema#decimal'/>" +
893 "</daml:DatatypeProperty>" +
894 "<daml:Datatype rdf:about='http://www.w3.org/2000/10/XMLSchema#decimal'/>";
895                 }
896                 void java(DAMLModel m) {
897                     DAMLDatatypeProperty shoeSize=m.createDAMLDatatypeProperty("http://example.org/#shoesize");
898                     shoeSize.setIsUnique(true);
899                     shoeSize.prop_range().add(
900                         m.createDAMLDatatype("http://www.w3.org/2000/10/XMLSchema#decimal") );
901                 }
902         });
903     }
904
905
906     /**
907      * Concept: the EqualityTest object embodies some java code that adds
908      * stuff to a DAMLModel, and some xml that is the body of an RDF/XML doc.
909      * This test checks that these two different ways of describing a DAML
910      * model are the same.
911      *
912      */

913     private void eqTest(EqualityTest test) {
914         DAMLModel m1 = getCleanModel();
915         test.java(m1);
916
917         Model m2 = ModelFactory.createDefaultModel();
918         Reader rdr = new StringReader(
919           "<rdf:RDF " +
920     "xmlns:daml='http://www.daml.org/2001/03/daml+oil#' " +
921     "xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>"
922      + test.xml()
923        + "</rdf:RDF>");
924        m2.read(rdr,"http://example.org/");
925
926        if (! m1.getBaseModel().isIsomorphicWith(m2) ) {
927            System.out.println("Java:");
928            m1.write(System.out,"RDF/XML-ABBREV");
929            System.out.println("XML:");
930            m2.write(System.out,"RDF/XML-ABBREV");
931        }
932
933        assertTrue("java code and xml should be equivalent",m1.getBaseModel().isIsomorphicWith(m2));
934
935    }
936
937    static abstract private class EqualityTest {
938        String JavaDoc name;
939        EqualityTest(String JavaDoc nm) {
940            name = nm;
941        }
942        public String JavaDoc toString() {
943            return name;
944        }
945        abstract void java(DAMLModel m);
946        abstract String JavaDoc xml();
947    }
948
949
950     /**
951      * Dump the model out to a file for debugging
952      */

953     public void dumpModel( Model m ) {
954         dumpModel( m, "model-out.rdf" );
955     }
956     public void dumpModel( Model m, String JavaDoc fileName ) {
957         try {
958             OutputStream f = new FileOutputStream(fileName);
959             m.write( f, "RDF/XML-ABBREV" );
960             f.close();
961         }
962         catch (Exception JavaDoc e) {
963            LogFactory.getLog( getClass() ).debug( "Exception while dumping model: " + e, e );
964         }
965
966     }
967
968
969     /**
970      * Count the number of things in an iterator, optionally logging them
971      */

972     private int countIteration( Iterator i, boolean doLog, String JavaDoc message ) {
973         int count = 0;
974         for (; i.hasNext(); count++) {
975             Object JavaDoc x = i.next();
976
977             if (doLog) {
978                 LogFactory.getLog( getClass() ).debug( "counting iteration, " + message + x );
979             }
980         }
981
982         return count;
983     }
984
985     private int countClasses( DAMLModel m ) {
986         return countIteration( m.listDAMLClasses(), true, "class = " );
987     }
988
989     private int countProperties( DAMLModel m ) {
990         return countIteration( m.listDAMLProperties(), true, "property = " );
991     }
992
993     private DAMLModel getCleanModel() {
994         DAMLModel m = ModelFactory.createDAMLModel();
995         m.getDocumentManager().setProcessImports(true);
996         m.getDocumentManager().clearCache();
997         m.getDocumentManager().setMetadataSearchPath( "file:etc/ont-policy-test.rdf", true );
998         List ll = new ArrayList();
999         for (Iterator i = m.getImportModelMaker().listModels(); i.hasNext(); ll.add( i.next() ) );
1000        for (Iterator i = ll.iterator(); i.hasNext(); ) {
1001            String JavaDoc mName = (String JavaDoc) i.next();
1002            m.getImportModelMaker().removeModel(mName);
1003            log.debug( "Removing " + mName );
1004        }
1005        return m;
1006    }
1007
1008    private void checkValidLists( Model m, String JavaDoc label ) {
1009        log.debug( "Checking lists in DAMLTest - " + label );
1010        for (StmtIterator i = m.listStatements(); i.hasNext(); ) {
1011            Statement s = i.nextStatement();
1012            RDFNode n = s.getObject();
1013            if (n instanceof Resource && ((Resource) n).canAs( RDFList.class )) {
1014                if (!((RDFList) n.as(RDFList.class)).isValid()) {
1015                    log.debug( "!!Found invalid list in " + label + " - " + n );
1016                    assertTrue( "DAML list not valid ", false );
1017                }
1018            }
1019        }
1020    }
1021
1022    //==============================================================================
1023
// Inner class definitions
1024
//==============================================================================
1025

1026
1027}
1028
1029
1030/*
1031    (c) Copyright 2001, 2002, 2003, 2004, 2005 Hewlett-Packard Development Company, LP
1032    All rights reserved.
1033
1034    Redistribution and use in source and binary forms, with or without
1035    modification, are permitted provided that the following conditions
1036    are met:
1037
1038    1. Redistributions of source code must retain the above copyright
1039       notice, this list of conditions and the following disclaimer.
1040
1041    2. Redistributions in binary form must reproduce the above copyright
1042       notice, this list of conditions and the following disclaimer in the
1043       documentation and/or other materials provided with the distribution.
1044
1045    3. The name of the author may not be used to endorse or promote products
1046       derived from this software without specific prior written permission.
1047
1048    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1049    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1050    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1051    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1052    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1053    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1054    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1055    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1056    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1057    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1058*/

1059
1060
Popular Tags