0001: /******************************************************************
0002: * File: TestBugs.java
0003: * Created by: Dave Reynolds
0004: * Created on: 22-Aug-2003
0005: *
0006: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
0007: * [See end of file]
0008: * $Id: TestBugs.java,v 1.53 2008/01/14 16:07:49 der Exp $
0009: *****************************************************************/package com.hp.hpl.jena.reasoner.rulesys.test;
0010:
0011: import java.io.*;
0012: import java.util.*;
0013:
0014: import junit.framework.TestCase;
0015: import junit.framework.TestSuite;
0016:
0017: import com.hp.hpl.jena.datatypes.TypeMapper;
0018: import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
0019: import com.hp.hpl.jena.graph.Node;
0020: import com.hp.hpl.jena.ontology.*;
0021: import com.hp.hpl.jena.rdf.listeners.StatementListener;
0022: import com.hp.hpl.jena.rdf.model.*;
0023: import com.hp.hpl.jena.reasoner.*;
0024: import com.hp.hpl.jena.reasoner.rulesys.*;
0025: import com.hp.hpl.jena.reasoner.rulesys.builtins.BaseBuiltin;
0026: import com.hp.hpl.jena.reasoner.test.TestUtil;
0027: import com.hp.hpl.jena.util.FileManager;
0028: import com.hp.hpl.jena.util.PrintUtil;
0029: import com.hp.hpl.jena.util.iterator.ClosableIterator;
0030: import com.hp.hpl.jena.util.iterator.ExtendedIterator;
0031: import com.hp.hpl.jena.vocabulary.*;
0032:
0033: /**
0034: * Unit tests for reported bugs in the rule system.
0035: *
0036: * @author <a href="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
0037: * @version $Revision: 1.53 $ on $Date: 2008/01/14 16:07:49 $
0038: */
0039: public class TestBugs extends TestCase {
0040:
0041: /**
0042: * Boilerplate for junit
0043: */
0044: public TestBugs(String name) {
0045: super (name);
0046: }
0047:
0048: /**
0049: * Boilerplate for junit.
0050: * This is its own test suite
0051: */
0052: public static TestSuite suite() {
0053: return new TestSuite(TestBugs.class);
0054: // TestSuite suite = new TestSuite();
0055: // suite.addTest(new TestBugs( "testOntModelGetDeductions" ));
0056: // return suite;
0057: }
0058:
0059: public void setUp() {
0060: // ensure the ont doc manager is in a consistent state
0061: OntDocumentManager.getInstance().reset(true);
0062: }
0063:
0064: /**
0065: * Report of NPE during processing on an ontology with a faulty intersection list,
0066: * from Hugh Winkler.
0067: */
0068: public void testIntersectionNPE() {
0069: Model base = ModelFactory.createDefaultModel();
0070: base.read("file:testing/reasoners/bugs/bad-intersection.owl");
0071: boolean foundBadList = false;
0072: try {
0073: InfGraph infgraph = ReasonerRegistry.getOWLReasoner().bind(
0074: base.getGraph());
0075: ExtendedIterator ci = infgraph.find(null, RDF.Nodes.type,
0076: OWL.Class.asNode());
0077: ci.close();
0078: } catch (ReasonerException e) {
0079: foundBadList = true;
0080: }
0081: assertTrue("Correctly detected the illegal list", foundBadList);
0082: }
0083:
0084: /**
0085: * Report of problems with cardinality v. maxCardinality usage in classification,
0086: * from Hugh Winkler.
0087: */
0088: public void testCardinality1() {
0089: Model base = ModelFactory.createDefaultModel();
0090: base.read("file:testing/reasoners/bugs/cardFPTest.owl");
0091: InfModel test = ModelFactory.createInfModel(ReasonerRegistry
0092: .getOWLReasoner(), base);
0093: String NAMESPACE = "urn:foo#";
0094: Resource aDocument = test.getResource(NAMESPACE + "aDocument");
0095: Resource documentType = test
0096: .getResource(NAMESPACE + "Document");
0097: assertTrue("Cardinality-based classification", test.contains(
0098: aDocument, RDF.type, documentType));
0099: }
0100:
0101: /**
0102: * Report of functor literals leaking out of inference graphs and raising CCE
0103: * in iterators.
0104: */
0105: public void testFunctorCCE() {
0106: Model base = ModelFactory.createDefaultModel();
0107: base.read("file:testing/reasoners/bugs/cceTest.owl");
0108: InfModel test = ModelFactory.createInfModel(ReasonerRegistry
0109: .getOWLReasoner(), base);
0110:
0111: boolean b = anyInstancesOfNothing(test);
0112: ResIterator rIter = test.listSubjects();
0113: while (rIter.hasNext()) {
0114: Resource res = rIter.nextResource();
0115: }
0116: }
0117:
0118: /** Helper function used in testFunctorCCE */
0119: private boolean anyInstancesOfNothing(Model model) {
0120: boolean hasAny = false;
0121: try {
0122: ExtendedIterator it = model.listStatements(null, RDF.type,
0123: OWL.Nothing);
0124: hasAny = it.hasNext();
0125: it.close();
0126: } catch (ConversionException x) {
0127: hasAny = false;
0128: }
0129: return hasAny;
0130: }
0131:
0132: public static final String INPUT_SUBCLASS = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
0133: + ""
0134: + "<rdf:RDF"
0135: + " xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\""
0136: + " xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\""
0137: + " xmlns:daml=\"http://www.daml.org/2001/03/daml+oil#\""
0138: + " xmlns:ex=\"http://localhost:8080/axis/daml/a.daml#\""
0139: + " xml:base=\"http://localhost:8080/axis/daml/a.daml\">"
0140: + " "
0141: + " <daml:Ontology rdf:about=\"\">"
0142: + " <daml:imports rdf:resource=\"http://www.daml.org/2001/03/daml+oil\"/>"
0143: + " </daml:Ontology>"
0144: + " "
0145: + " <daml:Class rdf:ID=\"cls1\"/>"
0146: + " <daml:Class rdf:ID=\"cls2\">"
0147: + " <daml:subClassOf rdf:resource=\"#cls1\"/>"
0148: + " </daml:Class>"
0149: + " <ex:cls2 rdf:ID=\"test\"/>"
0150: + "</rdf:RDF>";
0151:
0152: /**
0153: * This test exposes an apparent problem in the reasoners. If the input data is
0154: * changed from daml:subClassOf to rdfs:subClassOf, the asserts all pass. As is,
0155: * the assert for res has rdf:type cls1 fails.
0156: */
0157: public void testSubClass() {
0158: OntModel model = ModelFactory.createOntologyModel(
0159: OntModelSpec.DAML_MEM_RDFS_INF, null);
0160: model.getDocumentManager().setMetadataSearchPath(
0161: "file:etc/ont-policy-test.rdf", true);
0162:
0163: String base = "http://localhost:8080/axis/daml/a.daml#";
0164: model.read(new ByteArrayInputStream(INPUT_SUBCLASS.getBytes()),
0165: base);
0166: OntResource res = (OntResource) model
0167: .getResource(base + "test").as(OntResource.class);
0168:
0169: OntClass cls1 = (OntClass) model.getResource(base + "cls1").as(
0170: OntClass.class);
0171: OntClass cls2 = (OntClass) model.getResource(base + "cls2").as(
0172: OntClass.class);
0173:
0174: assertTrue("cls2 should be a super-class of cls1", cls2
0175: .hasSuperClass(cls1));
0176: assertTrue("res should have rdf:type cls1", res
0177: .hasRDFType(cls1));
0178: assertTrue("res should have rdf:type cls2", res
0179: .hasRDFType(cls2));
0180: }
0181:
0182: public static final String INPUT_SUBPROPERTY = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
0183: + ""
0184: + "<rdf:RDF"
0185: + " xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\""
0186: + " xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\""
0187: + " xmlns:daml=\"http://www.daml.org/2001/03/daml+oil#\""
0188: + " xmlns=\"urn:x-hp-jena:test#\""
0189: + " xml:base=\"urn:x-hp-jena:test\">"
0190: + " "
0191: + " <daml:Ontology rdf:about=\"\">"
0192: + " <daml:imports rdf:resource=\"http://www.daml.org/2001/03/daml+oil\"/>"
0193: + " </daml:Ontology>"
0194: + " "
0195: + " <daml:Class rdf:ID=\"A\"/>"
0196: + ""
0197: + " <daml:ObjectProperty rdf:ID=\"p\" />"
0198: + " <daml:ObjectProperty rdf:ID=\"q\">"
0199: + " <daml:subPropertyOf rdf:resource=\"#p\"/>"
0200: + " </daml:ObjectProperty>"
0201: + ""
0202: + " <A rdf:ID=\"a0\"/>"
0203: + " <A rdf:ID=\"a1\">"
0204: + " <q rdf:resource=\"#a0\" />"
0205: + " </A>"
0206: + "</rdf:RDF>";
0207:
0208: /**
0209: * This test exposes an apparent problem in the reasoners. If the input data is
0210: * changed from daml:subPropertyOf to rdfs:subPropertyOf, the asserts all pass. As is,
0211: * the assert for a1 p a0 fails.
0212: */
0213: public void testSubProperty() {
0214: OntModel model = ModelFactory.createOntologyModel(
0215: OntModelSpec.DAML_MEM_RDFS_INF, null);
0216: model.getDocumentManager().setMetadataSearchPath(
0217: "file:etc/ont-policy-test.rdf", true);
0218:
0219: String base = "urn:x-hp-jena:test#";
0220: model.read(new ByteArrayInputStream(INPUT_SUBPROPERTY
0221: .getBytes()), base);
0222:
0223: OntResource a0 = (OntResource) model.getResource(base + "a0")
0224: .as(OntResource.class);
0225: OntResource a1 = (OntResource) model.getResource(base + "a1")
0226: .as(OntResource.class);
0227:
0228: ObjectProperty p = model.getObjectProperty(base + "p");
0229: ObjectProperty q = model.getObjectProperty(base + "q");
0230:
0231: assertTrue("subProp relation present", q.hasProperty(
0232: RDFS.subPropertyOf, p));
0233: assertTrue("a1 q a0", a1.hasProperty(q, a0)); // asserted
0234: assertTrue("a1 p a0", a1.hasProperty(p, a0)); // entailed
0235: }
0236:
0237: /**
0238: * Test problems with inferring equivalence of some simple class definitions,
0239: * reported by Jeffrey Hau.
0240: */
0241: public void testEquivalentClass1() {
0242: Model base = ModelFactory.createDefaultModel();
0243: base
0244: .read("file:testing/reasoners/bugs/equivalentClassTest.owl");
0245: InfModel test = ModelFactory.createInfModel(ReasonerRegistry
0246: .getOWLReasoner(), base);
0247: String NAMESPACE = "urn:foo#";
0248: Resource A = test.getResource(NAMESPACE + "A");
0249: Resource B = test.getResource(NAMESPACE + "B");
0250: assertTrue("hasValue equiv deduction", test.contains(A,
0251: OWL.equivalentClass, B));
0252: }
0253:
0254: /**
0255: * Test reported problem with OWL property axioms.
0256: */
0257: public void testOWLPropertyAxioms() {
0258: Model data = ModelFactory.createDefaultModel();
0259: Resource fp = data.createResource("urn:x-hp:eg/fp");
0260: Resource ifp = data.createResource("urn:x-hp:eg/ifp");
0261: Resource tp = data.createResource("urn:x-hp:eg/tp");
0262: Resource sp = data.createResource("urn:x-hp:eg/sp");
0263: data.add(fp, RDF.type, OWL.FunctionalProperty);
0264: data.add(ifp, RDF.type, OWL.InverseFunctionalProperty);
0265: data.add(tp, RDF.type, OWL.TransitiveProperty);
0266: data.add(sp, RDF.type, OWL.SymmetricProperty);
0267: InfModel infmodel = ModelFactory.createInfModel(
0268: ReasonerRegistry.getOWLReasoner(), data);
0269: assertTrue("property class axioms", infmodel.contains(fp,
0270: RDF.type, RDF.Property));
0271: assertTrue("property class axioms", infmodel.contains(ifp,
0272: RDF.type, RDF.Property));
0273: assertTrue("property class axioms", infmodel.contains(tp,
0274: RDF.type, RDF.Property));
0275: assertTrue("property class axioms", infmodel.contains(sp,
0276: RDF.type, RDF.Property));
0277: assertTrue("property class axioms", infmodel.contains(ifp,
0278: RDF.type, OWL.ObjectProperty));
0279: assertTrue("property class axioms", infmodel.contains(tp,
0280: RDF.type, OWL.ObjectProperty));
0281: assertTrue("property class axioms", infmodel.contains(sp,
0282: RDF.type, OWL.ObjectProperty));
0283: }
0284:
0285: /**
0286: * Test for a reported bug in delete
0287: */
0288: public void testDeleteBug() {
0289: Model modelo = ModelFactory.createDefaultModel();
0290: modelo.read("file:testing/reasoners/bugs/deleteBug.owl");
0291: OntModel modeloOnt = ModelFactory.createOntologyModel(
0292: OntModelSpec.OWL_MEM_RULE_INF, modelo);
0293: Individual indi = modeloOnt
0294: .getIndividual("http://decsai.ugr.es/~ontoserver/bacarex2.owl#JS");
0295: indi.remove();
0296: ClosableIterator it = modeloOnt.listStatements(indi, null,
0297: (RDFNode) null);
0298: boolean ok = !it.hasNext();
0299: it.close();
0300: assertTrue(ok);
0301: }
0302:
0303: /**
0304: * Test bug caused by caching of deductions models.
0305: */
0306: public void testDeteleBug2() {
0307: Model m = ModelFactory.createDefaultModel();
0308: String NS = PrintUtil.egNS;
0309: Resource r = m.createResource(NS + "r");
0310: Resource A = m.createResource(NS + "A");
0311: Resource B = m.createResource(NS + "B");
0312: Statement s = m.createStatement(r, RDF.type, A);
0313: m.add(s);
0314: String rules = "(?r rdf:type eg:A) -> (?r rdf:type eg:B).";
0315: GenericRuleReasoner grr = new GenericRuleReasoner(Rule
0316: .parseRules(rules));
0317: InfModel im = ModelFactory.createInfModel(grr, m);
0318: assertTrue(im.contains(r, RDF.type, B));
0319: assertTrue(im.getDeductionsModel().contains(r, RDF.type, B));
0320: im.remove(s);
0321: assertFalse(im.contains(r, RDF.type, B));
0322: assertFalse(im.getDeductionsModel().contains(r, RDF.type, B));
0323: }
0324:
0325: /**
0326: * Test looping on recursive someValuesFrom.
0327: */
0328: public void hiddenTestOWLLoop() {
0329: Model data = FileManager.get().loadModel(
0330: "file:testing/reasoners/bugs/loop.owl");
0331: InfModel infmodel = ModelFactory.createInfModel(
0332: ReasonerRegistry.getOWLReasoner(), data);
0333: ((FBRuleInfGraph) infmodel.getGraph()).setTraceOn(true);
0334: String baseURI = "http://jena.hpl.hp.com/eg#";
0335: Resource C = infmodel.getResource(baseURI + "C");
0336: Resource I = infmodel.getResource(baseURI + "i");
0337: Property R = infmodel.getProperty(baseURI, "R");
0338: // ((FBRuleInfGraph)infmodel.getGraph()).setTraceOn(true);
0339: System.out
0340: .println("Check that the instance does have an R property");
0341: Statement s = I.getProperty(R);
0342: System.out.println(" - " + s);
0343: System.out.println("And that the type of the R property is C");
0344: Statement s2 = ((Resource) s.getObject()).getProperty(RDF.type);
0345: System.out.println(" - " + s2);
0346: System.out.println("But does that have an R property?");
0347: Statement s3 = ((Resource) s.getObject()).getProperty(R);
0348: System.out.println(" - " + s3);
0349: System.out.println("List all instances of C");
0350: int count = 0;
0351: for (Iterator i = infmodel.listStatements(null, RDF.type, C); i
0352: .hasNext();) {
0353: Statement st = (Statement) i.next();
0354: System.out.println(" - " + st);
0355: count++;
0356: }
0357: System.out.println("OK");
0358: // infmodel.write(System.out);
0359: // System.out.flush();
0360: }
0361:
0362: /**
0363: * Test bug with leaking variables which results in an incorrect "range = Nothing" deduction.
0364: */
0365: public void testRangeBug() {
0366: Model model = FileManager.get().loadModel(
0367: "file:testing/reasoners/bugs/rangeBug.owl");
0368: Model m = ModelFactory.createDefaultModel();
0369: Reasoner r = ReasonerRegistry.getOWLReasoner();
0370: InfModel omodel = ModelFactory.createInfModel(r, model);
0371: String baseuri = "http://decsai.ugr.es/~ontoserver/bacarex2.owl#";
0372: Resource js = omodel.getResource(baseuri + "JS");
0373: Resource surname = omodel.getResource(baseuri + "surname");
0374: Statement s = omodel.createStatement(surname, RDFS.range,
0375: OWL.Nothing);
0376: assertTrue(!omodel.contains(s));
0377: }
0378:
0379: /**
0380: * Test change of RDF specs to allow plain literals w/o lang and XSD string to be the same.
0381: */
0382: public void testLiteralBug() {
0383: Model model = FileManager.get().loadModel(
0384: "file:testing/reasoners/bugs/dtValidation.owl");
0385: Model m = ModelFactory.createDefaultModel();
0386: Reasoner r = ReasonerRegistry.getOWLReasoner();
0387: InfModel infmodel = ModelFactory.createInfModel(r, model);
0388: ValidityReport validity = infmodel.validate();
0389: assertTrue(validity.isValid());
0390: }
0391:
0392: /**
0393: * Test that prototype nodes are now hidden
0394: */
0395: public void testHide() {
0396: String NS = "http://jena.hpl.hp.com/bugs#";
0397: OntModel m = ModelFactory.createOntologyModel(
0398: OntModelSpec.OWL_MEM_RULE_INF, null);
0399: OntClass c = m.createClass(NS + "C");
0400: OntResource i = m.createIndividual(c);
0401: Iterator res = m.listStatements(null, RDF.type, c);
0402: TestUtil.assertIteratorValues(this , res, new Statement[] { m
0403: .createStatement(i, RDF.type, c) });
0404: }
0405:
0406: /**
0407: * Also want to have hidden rb:xsdRange
0408: */
0409: public void testHideXSDRange() {
0410: OntModelSpec[] specs = new OntModelSpec[] {
0411: OntModelSpec.OWL_MEM_RULE_INF,
0412: OntModelSpec.OWL_MEM_RDFS_INF,
0413: OntModelSpec.OWL_MEM_MINI_RULE_INF,
0414: OntModelSpec.OWL_MEM_MICRO_RULE_INF };
0415: for (int os = 0; os < specs.length; os++) {
0416: OntModelSpec spec = specs[os];
0417: OntModel m = ModelFactory.createOntologyModel(spec, null);
0418: Iterator i = m.listOntProperties();
0419: while (i.hasNext()) {
0420: Resource r = (Resource) i.next();
0421: if (r.getURI() != null
0422: && r.getURI().startsWith(
0423: ReasonerVocabulary.RBNamespace)) {
0424: assertTrue("Rubrik internal property leaked out: "
0425: + r + "(" + os + ")", false);
0426: }
0427: }
0428: }
0429: }
0430:
0431: /**
0432: * Test problem with bindSchema not interacting properly with validation.
0433: */
0434: public void testBindSchemaValidate() {
0435: Reasoner reasoner = ReasonerRegistry.getOWLReasoner();
0436: Model schema = FileManager.get().loadModel(
0437: "file:testing/reasoners/bugs/sbug.owl");
0438: Model data = FileManager.get().loadModel(
0439: "file:testing/reasoners/bugs/sbug.rdf");
0440:
0441: // Union version
0442: InfModel infu = ModelFactory.createInfModel(reasoner, data
0443: .union(schema));
0444: ValidityReport validity = infu.validate();
0445: assertTrue(!validity.isValid());
0446: // debug print
0447: // for (Iterator i = validity.getReports(); i.hasNext(); ) {
0448: // System.out.println(" - " + i.next());
0449: // }
0450:
0451: // bindSchema version
0452: InfModel inf = ModelFactory.createInfModel(reasoner
0453: .bindSchema(schema), data);
0454: validity = inf.validate();
0455: assertTrue(!validity.isValid());
0456: }
0457:
0458: /**
0459: * Delete bug in generic rule reasoner.
0460: */
0461: public void testGenericDeleteBug() {
0462: Model data = ModelFactory.createDefaultModel();
0463: String NS = "urn:x-hp:eg/";
0464: Property p = data.createProperty(NS, "p");
0465: Resource x = data.createResource(NS + "x");
0466: Resource y = data.createResource(NS + "y");
0467: Statement sy = data.createStatement(y, p, "foo");
0468: data.add(sy);
0469: data.add(x, p, "foo");
0470: // String rule = "[(?x eg:p ?m) -> (?x eg:same ?x)]";
0471: String rule = "[(?x eg:p ?m) (?y eg:p ?m) -> (?x eg:same ?y) (?y eg:same ?x)]";
0472: GenericRuleReasoner reasoner = (GenericRuleReasoner) GenericRuleReasonerFactory
0473: .theInstance().create(null);
0474: reasoner.setMode(GenericRuleReasoner.FORWARD_RETE);
0475: reasoner.setRules(Rule.parseRules(rule));
0476: InfModel inf = ModelFactory.createInfModel(reasoner, data);
0477: TestUtil.assertIteratorLength(inf.listStatements(y, null,
0478: (RDFNode) null), 3);
0479: inf.remove(sy);
0480: TestUtil.assertIteratorLength(inf.listStatements(y, null,
0481: (RDFNode) null), 0);
0482: }
0483:
0484: /**
0485: * RETE incremental processing bug.
0486: */
0487: public void testRETEInc() {
0488: String rule = "(?x ?p ?y) -> (?p rdf:type rdf:Property) .";
0489: Reasoner r = new GenericRuleReasoner(Rule.parseRules(rule));
0490: InfModel m = ModelFactory.createInfModel(r, ModelFactory
0491: .createDefaultModel());
0492:
0493: Resource source = m.createResource("urn:alfie:testResource");
0494: Property prop = m.createProperty("urn:alfie:testProperty");
0495: Statement s1 = m.createStatement(source, prop, "value1");
0496: Statement s2 = m.createStatement(source, prop, "value2");
0497:
0498: m.add(s1);
0499: assertIsProperty(m, prop);
0500: m.add(s2);
0501: m.remove(s1);
0502: assertIsProperty(m, prop);
0503: }
0504:
0505: /**
0506: * RETE incremental processing bug.
0507: */
0508: public void testRETEDec() {
0509: String rule = "(?x ?p ?y) -> (?p rdf:type rdf:Property) .";
0510: Reasoner r = new GenericRuleReasoner(Rule.parseRules(rule));
0511: InfModel m = ModelFactory.createInfModel(r, ModelFactory
0512: .createDefaultModel());
0513:
0514: Resource source = m.createResource("urn:alfie:testResource");
0515: Property prop = m.createProperty("urn:alfie:testProperty");
0516: Statement s1 = m.createStatement(source, prop, "value1");
0517: Statement s2 = m.createStatement(source, prop, "value2");
0518:
0519: m.add(prop, RDF.type, RDF.Property);
0520: m.add(s1);
0521: m.prepare();
0522: m.remove(s1);
0523: assertIsProperty(m, prop);
0524: }
0525:
0526: private void assertIsProperty(Model m, Property prop) {
0527: assertTrue(m.contains(prop, RDF.type, RDF.Property));
0528: }
0529:
0530: /**
0531: * Bug that exposed prototypes of owl:Thing despite hiding being switched on.
0532: */
0533: public void testHideOnOWLThing() {
0534: Reasoner r = ReasonerRegistry.getOWLReasoner();
0535: Model data = ModelFactory.createDefaultModel();
0536: InfModel inf = ModelFactory.createInfModel(r, data);
0537: StmtIterator things = inf.listStatements(null, RDF.type,
0538: OWL.Thing);
0539: TestUtil.assertIteratorLength(things, 0);
0540: }
0541:
0542: /**
0543: * Limitation of someValuesFrom applied to datatype properties.
0544: */
0545: public void testSomeDatatype() throws IOException {
0546: String uri = "http://www.daml.org/2001/03/daml+oil-ex-dt";
0547: String filename = "testing/xsd/daml+oil-ex-dt.xsd";
0548: TypeMapper tm = TypeMapper.getInstance();
0549: XSDDatatype.loadUserDefined(uri, new FileReader(filename),
0550: null, tm);
0551:
0552: Model data = ModelFactory.createDefaultModel();
0553: data.read("file:testing/reasoners/bugs/userDatatypes.owl");
0554: InfModel inf = ModelFactory.createInfModel(ReasonerRegistry
0555: .getOWLReasoner(), data);
0556:
0557: String egNS = "http://jena.hpl.hp.com/eg#";
0558: Resource meR = inf.getResource(egNS + "me");
0559: Resource TestR = inf.getResource(egNS + "Test");
0560: assertTrue("somevalues inf for datatypes", inf.contains(meR,
0561: RDF.type, TestR));
0562:
0563: Resource Test2R = inf.getResource(egNS + "Test2");
0564: Resource me2R = inf.getResource(egNS + "me2");
0565: assertTrue("somevalues inf for datatypes", inf.contains(me2R,
0566: RDF.type, Test2R));
0567: assertTrue("somevalues inf for user datatypes", inf.contains(
0568: meR, RDF.type, Test2R));
0569: }
0570:
0571: /* Report on jena-dev that DAMLMicroReasoner infmodels don't support daml:subClassOf, etc */
0572: public void testDAMLMicroReasonerSupports() {
0573: Reasoner r = DAMLMicroReasonerFactory.theInstance()
0574: .create(null);
0575: assertTrue("Should support daml:subClassOf", r
0576: .supportsProperty(DAML_OIL.subClassOf));
0577: assertTrue("Should support daml:subPropertyOf", r
0578: .supportsProperty(DAML_OIL.subPropertyOf));
0579: assertTrue("Should support daml:domain", r
0580: .supportsProperty(DAML_OIL.domain));
0581: assertTrue("Should support daml:range", r
0582: .supportsProperty(DAML_OIL.range));
0583: }
0584:
0585: /**
0586: * Utility function.
0587: * Create a model from an N3 string with OWL and EG namespaces defined.
0588: */
0589: public static Model modelFromN3(String src) {
0590: String fullSource = "@prefix owl: <http://www.w3.org/2002/07/owl#> .\n"
0591: + "@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n"
0592: + "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n"
0593: + "@prefix eg: <http://jena.hpl.hp.com/eg#> .\n"
0594: + "@prefix : <#> .\n" + src + "\n";
0595: Model result = ModelFactory.createDefaultModel();
0596: result.read(new StringReader(fullSource), "", "N3");
0597: return result;
0598: }
0599:
0600: /** Bug report from Ole Hjalmar - direct subClassOf not reporting correct result with rule reasoner */
0601: public void test_oh_01() {
0602: String NS = "http://www.idi.ntnu.no/~herje/ja/";
0603: Resource[] expected = new Resource[] {
0604: ResourceFactory.createResource(NS
0605: + "reiseliv.owl#Reiseliv"),
0606: ResourceFactory
0607: .createResource(NS + "hotell.owl#Hotell"),
0608: ResourceFactory.createResource(NS
0609: + "restaurant.owl#Restaurant"),
0610: ResourceFactory.createResource(NS
0611: + "restaurant.owl#UteRestaurant"),
0612: ResourceFactory.createResource(NS
0613: + "restaurant.owl#UteBadRestaurant"),
0614: ResourceFactory.createResource(NS
0615: + "restaurant.owl#UteDoRestaurant"),
0616: ResourceFactory.createResource(NS
0617: + "restaurant.owl#SkogRestaurant"), };
0618:
0619: test_oh_01scan(OntModelSpec.OWL_MEM, "No inf", expected);
0620: test_oh_01scan(OntModelSpec.OWL_MEM_MINI_RULE_INF,
0621: "Mini rule inf", expected);
0622: test_oh_01scan(OntModelSpec.OWL_MEM_MICRO_RULE_INF,
0623: "Micro rule inf", expected);
0624: test_oh_01scan(OntModelSpec.OWL_MEM_RULE_INF, "Full rule inf",
0625: expected);
0626: }
0627:
0628: /** Problem with bindSchema and validation rules */
0629: public void test_der_validation() {
0630: Model abox = FileManager.get().loadModel(
0631: "file:testing/reasoners/owl/nondetbug.rdf");
0632: List rules = FBRuleReasoner
0633: .loadRules("testing/reasoners/owl/nondetbug.rules");
0634: GenericRuleReasoner r = new GenericRuleReasoner(rules);
0635: // r.setTraceOn(true);
0636: for (int i = 0; i < 10; i++) {
0637: InfModel im = ModelFactory.createInfModel(r, abox);
0638: assertTrue("failed on count " + i, im.contains(null,
0639: ReasonerVocabulary.RB_VALIDATION_REPORT,
0640: (RDFNode) null));
0641: }
0642: }
0643:
0644: // Temporary for debug
0645: private void test_oh_01scan(OntModelSpec s, String prompt,
0646: Resource[] expected) {
0647: String NS = "http://www.idi.ntnu.no/~herje/ja/reiseliv.owl#";
0648: OntModel m = ModelFactory.createOntologyModel(s, null);
0649: m.read("file:testing/ontology/bugs/test_oh_01.owl");
0650:
0651: // System.out.println( prompt );
0652: OntClass r = m.getOntClass(NS + "Reiseliv");
0653:
0654: List q = new ArrayList();
0655: Set seen = new HashSet();
0656: q.add(r);
0657:
0658: while (!q.isEmpty()) {
0659: OntClass c = (OntClass) q.remove(0);
0660: seen.add(c);
0661:
0662: for (Iterator i = c.listSubClasses(true); i.hasNext();) {
0663: OntClass sub = (OntClass) i.next();
0664: if (!seen.contains(sub)) {
0665: q.add(sub);
0666: }
0667: }
0668:
0669: // System.out.println( " Seen class " + c );
0670: }
0671:
0672: // check we got all classes
0673: int mask = (1 << expected.length) - 1;
0674:
0675: for (int j = 0; j < expected.length; j++) {
0676: if (seen.contains(expected[j])) {
0677: mask &= ~(1 << j);
0678: } else {
0679: // System.out.println( "Expected but did not see " + expected[j] );
0680: }
0681: }
0682:
0683: for (Iterator k = seen.iterator(); k.hasNext();) {
0684: Resource res = (Resource) k.next();
0685: boolean isExpected = false;
0686: for (int j = 0; !isExpected && j < expected.length; j++) {
0687: isExpected = expected[j].equals(res);
0688: }
0689: if (!isExpected) {
0690: // System.out.println( "Got unexpected result " + res );
0691: }
0692: }
0693:
0694: assertEquals("Some expected results were not seen", 0, mask);
0695: }
0696:
0697: /**
0698: * Bug report from David A Bigwood
0699: */
0700: public void test_domainInf() {
0701: // create an OntModel
0702: OntModel m = ModelFactory.createOntologyModel(
0703: OntModelSpec.OWL_MEM_RULE_INF, null);
0704: // populate the model with stuff
0705: String NS = "http://m3t4.com/ont/#";
0706: OntClass c1 = m.createClass(NS + "c1");
0707: OntClass c2 = m.createClass(NS + "c2");
0708: OntClass c3 = m.createClass(NS + "c3");
0709: OntProperty p1 = m.createObjectProperty(NS + "p1");
0710: // create a union class to contain the union operands
0711: UnionClass uc = m.createUnionClass(null, null);
0712: // add an operand
0713: uc.addOperand(c1);
0714: assertEquals("Size should be 1", 1, uc.getOperands().size());
0715: assertTrue("uc should have c1 as union member", uc
0716: .getOperands().contains(c1));
0717: // add another operand
0718: uc.addOperand(c2);
0719: assertEquals("Size should be 2", 2, uc.getOperands().size());
0720: TestUtil.assertIteratorValues(this , uc.listOperands(),
0721: new Object[] { c1, c2 });
0722: // add a third operand
0723: uc.addOperand(c3);
0724: assertEquals("Size should be 3", 3, uc.getOperands().size());
0725: TestUtil.assertIteratorValues(this , uc.listOperands(),
0726: new Object[] { c1, c2, c3 });
0727: // add union class as domain of a property
0728: p1.addDomain(uc);
0729: }
0730:
0731: /**
0732: * Bug report on bad conflict resolution between two non-monotonic rules.
0733: */
0734: public void testNonmonotonicCR() {
0735: String ruleSrc = "(eg:IndA eg:scoreA ?score), sum(?score 40 ?total), noValue(eg:IndA eg:flag_1 'true') -> drop(0), (eg:IndA eg:scoreA ?total), (eg:IndA eg:flag_1 'true')."
0736: + "(eg:IndA eg:scoreA ?score), sum(?score 33 ?total), noValue(eg:IndA eg:flag_2 'true') -> drop(0), (eg:IndA eg:scoreA ?total), (eg:IndA eg:flag_2 'true').";
0737: List rules = Rule.parseRules(ruleSrc);
0738: Model data = ModelFactory.createDefaultModel();
0739: String NS = PrintUtil.egNS;
0740: Resource i = data.createResource(NS + "IndA");
0741: Property scoreA = data.createProperty(NS, "scoreA");
0742: i.addProperty(scoreA, data.createTypedLiteral(100));
0743: GenericRuleReasoner reasoner = new GenericRuleReasoner(rules);
0744: InfModel inf = ModelFactory.createInfModel(reasoner, data);
0745: Iterator values = inf.listObjectsOfProperty(i, scoreA);
0746: TestUtil.assertIteratorValues(this , values, new Object[] { data
0747: .createTypedLiteral(173) });
0748: }
0749:
0750: /**
0751: * Bug report - intersection processing does not work incrementally.
0752: */
0753: public void testIncrementalIU() {
0754: OntModel ontmodel = ModelFactory
0755: .createOntologyModel(OntModelSpec.OWL_MEM_MINI_RULE_INF);
0756: String homeuri = "http://abc/bcd/";
0757:
0758: Individual ind[] = new Individual[6];
0759: OntClass classb = ontmodel.createClass(homeuri + "C");
0760: for (int i = 0; i < 6; i++) {
0761: ind[i] = classb.createIndividual(homeuri
0762: + String.valueOf(i));
0763: }
0764: Individual subind[] = new Individual[] { ind[0], ind[1], ind[2] };
0765:
0766: EnumeratedClass class1 = ontmodel.createEnumeratedClass(homeuri
0767: + "C1", ontmodel.createList(subind));
0768: EnumeratedClass class2 = ontmodel.createEnumeratedClass(homeuri
0769: + "C2", ontmodel.createList(ind));
0770:
0771: RDFList list = ontmodel.createList(new RDFNode[] { class1,
0772: class2 });
0773: IntersectionClass classI = ontmodel.createIntersectionClass(
0774: null, list);
0775: UnionClass classU = ontmodel.createUnionClass(null, list);
0776:
0777: // Works with rebind, bug is that it doesn't work without rebind
0778: // ontmodel.rebind();
0779:
0780: TestUtil.assertIteratorValues(this , classI.listInstances(),
0781: subind);
0782: TestUtil
0783: .assertIteratorValues(this , classU.listInstances(), ind);
0784: }
0785:
0786: /**
0787: * Fact rules with non-empty bodyies failed to fire.
0788: */
0789: public void testFactRules() {
0790: Model facts = ModelFactory.createDefaultModel();
0791: String NS = PrintUtil.egNS;
0792: Property p = facts.createProperty(NS + "p");
0793: List rules = Rule
0794: .parseRules("makeTemp(?x) -> (?x, eg:p, eg:z). "
0795: + "makeTemp(?x) makeTemp(?y) -> (?x, eg:p, ?y) . "
0796: + "(?x, eg:p, eg:z) -> (?a, eg:p, eg:b). "
0797: + "-> [ (eg:a eg:p eg:y) <- ].");
0798:
0799: GenericRuleReasoner reasoner = new GenericRuleReasoner(rules);
0800: InfModel inf = ModelFactory.createInfModel(reasoner, facts);
0801: inf.prepare();
0802: TestUtil.assertIteratorLength(inf.listStatements(null, p,
0803: (RDFNode) null), 4);
0804: }
0805:
0806: /**
0807: * Test chainging rules from axioms which broke while trying to
0808: * fix about test case.
0809: */
0810: public void testFactChainRules() {
0811: Model facts = ModelFactory.createDefaultModel();
0812: String NS = PrintUtil.egNS;
0813: Property mother = facts.createProperty(NS + "mother");
0814: Resource female = facts.createProperty(NS + "Female");
0815: mother.addProperty(RDFS.range, female);
0816: List rules = Rule
0817: .parseRules("-> tableAll(). \n"
0818: + "[rdfs6: (?p rdfs:subPropertyOf ?q), notEqual(?p,?q) -> [ (?a ?q ?b) <- (?a ?p ?b)] ] \n"
0819: + "-> (eg:range rdfs:subPropertyOf rdfs:range). \n"
0820: + "-> (rdfs:range rdfs:subPropertyOf eg:range). \n");
0821: GenericRuleReasoner reasoner = new GenericRuleReasoner(rules);
0822: reasoner.setTransitiveClosureCaching(true);
0823: InfModel inf = ModelFactory.createInfModel(reasoner, facts);
0824: Property egRange = inf.createProperty(NS + "range");
0825: TestUtil.assertIteratorValues(this , inf.listStatements(null,
0826: egRange, (RDFNode) null), new Object[] { inf
0827: .createStatement(mother, egRange, female) });
0828: }
0829:
0830: /**
0831: * test remove operator in case with empty data.
0832: */
0833: public void testEmptyRemove() {
0834: List rules = Rule
0835: .parseRules("-> (eg:i eg:prop eg:foo) ."
0836: + "(?X eg:prop ?V) -> (?X eg:prop2 ?V) ."
0837: + "(?X eg:prop eg:foo) noValue(?X eg:guard 'done') -> remove(0) (?X eg:guard 'done') .");
0838: GenericRuleReasoner reasoner = new GenericRuleReasoner(rules);
0839: InfModel im = ModelFactory.createInfModel(reasoner,
0840: ModelFactory.createDefaultModel());
0841: Resource i = im.createResource(PrintUtil.egNS + "i");
0842: Property guard = im.createProperty(PrintUtil.egNS + "guard");
0843: TestUtil.assertIteratorValues(this , im.listStatements(),
0844: new Object[] { im.createStatement(i, guard, "done") });
0845: }
0846:
0847: /**
0848: * test duplicate removal when using pure backward rules
0849: */
0850: public void testBackwardDupRemoval() {
0851: String NS = PrintUtil.egNS;
0852: Model base = ModelFactory.createDefaultModel();
0853: Resource i = base.createResource(NS + "i");
0854: Resource a = base.createResource(NS + "a");
0855: Property p = base.createProperty(NS, "p");
0856: Property q = base.createProperty(NS, "q");
0857: Property r = base.createProperty(NS, "r");
0858: base.add(i, p, a);
0859: base.add(i, q, a);
0860: List rules = Rule
0861: .parseRules("(eg:i eg:r eg:a) <- (eg:i eg:p eg:a). (eg:i eg:r eg:a) <- (eg:i eg:q eg:a).");
0862: GenericRuleReasoner reasoner = new GenericRuleReasoner(rules);
0863: reasoner.setMode(GenericRuleReasoner.BACKWARD);
0864: InfModel im = ModelFactory.createInfModel(reasoner, base);
0865: TestUtil.assertIteratorLength(im.listStatements(i, r, a), 1);
0866: }
0867:
0868: /**
0869: * Test closure of grounded choice points
0870: */
0871: public void testGroundClosure() {
0872: Flag myFlag = new Flag();
0873: BuiltinRegistry.theRegistry.register(myFlag);
0874: String NS = "http://ont.com/";
0875: PrintUtil.registerPrefix("ns", NS);
0876: String rules = "[r1: (ns:a ns:p ns:b) <- (ns:a ns:p ns:a)] "
0877: + "[r2: (ns:a ns:p ns:b) <- flag()] "
0878: + "[rt: (?a ns:q ?b) <- (?a ns:p ?b)] ";
0879: Model m = ModelFactory.createDefaultModel();
0880: Resource a = m.createResource(NS + "a");
0881: Resource b = m.createResource(NS + "b");
0882: Property p = m.createProperty(NS + "p");
0883: Property q = m.createProperty(NS + "q");
0884: m.add(a, p, a);
0885: GenericRuleReasoner reasoner = new GenericRuleReasoner(Rule
0886: .parseRules(rules));
0887: InfModel infModel = ModelFactory.createInfModel(reasoner, m);
0888: assertTrue(infModel.contains(a, q, b));
0889: assertTrue(!myFlag.fired);
0890: }
0891:
0892: /**
0893: * Test case for a reported CME bug in the transitive reasoner
0894: */
0895: public void testCMEInTrans() {
0896: OntModel model = ModelFactory
0897: .createOntologyModel(OntModelSpec.OWL_DL_MEM_TRANS_INF);
0898: model.read("file:testing/reasoners/bugs/tgcCMEbug.owl");
0899: }
0900:
0901: /**
0902: * Test case for reported problem in detecting cardinality violations
0903: */
0904: public void testIndCardValidation() {
0905: final String NS = "http://dummy#";
0906:
0907: // prepare TBox
0908: OntModel tBox = ModelFactory
0909: .createOntologyModel(OntModelSpec.OWL_DL_MEM);
0910: OntClass moleculeClass = tBox.createClass(NS + "Molecule");
0911: // add value constraint on molecule2atom
0912: ObjectProperty molecule2atomOntProperty = tBox
0913: .createObjectProperty(NS + "molecule2atom");
0914: molecule2atomOntProperty.setDomain(moleculeClass);
0915: molecule2atomOntProperty.setRange(RDF.Bag);
0916: // add cardinality constraint on molecule2atom
0917: CardinalityRestriction molecule2atomCardinalityRestriction = tBox
0918: .createCardinalityRestriction(null,
0919: molecule2atomOntProperty, 1);
0920: moleculeClass
0921: .addSuperClass(molecule2atomCardinalityRestriction);
0922:
0923: // prepare ABox
0924: Reasoner reasoner = ReasonerRegistry.getOWLReasoner();
0925: reasoner = reasoner.bindSchema(tBox);
0926: Model model = ModelFactory.createDefaultModel();
0927: InfModel aBox = ModelFactory.createInfModel(reasoner, model);
0928:
0929: // make sure rdfs:member properties are inferred
0930: // ((FBRuleInfGraph)aBox.getGraph()).addPreprocessingHook(new RDFSCMPPreprocessHook());
0931:
0932: // create an invalid molecule
0933: Bag bag1 = aBox.createBag();
0934: Bag bag2 = aBox.createBag();
0935: bag1.addProperty(OWL.differentFrom, bag2);
0936: Resource molecule = aBox.createResource();
0937: molecule.addProperty(molecule2atomOntProperty, bag1);
0938: molecule.addProperty(molecule2atomOntProperty, bag2);
0939:
0940: // check if model has become invalid
0941: assertTrue(aBox.contains(molecule, RDF.type, moleculeClass));
0942: assertFalse(aBox.validate().isValid()); // fails: why?
0943: }
0944:
0945: /**
0946: * Listeners on deductions graph should be preserved across rebind operations
0947: */
0948: public void testDeductionListener() {
0949: final String NS = PrintUtil.egNS;
0950:
0951: // Data: (eg:i eg:p 'foo')
0952: Model base = ModelFactory.createDefaultModel();
0953: Resource i = base.createResource(NS + "i");
0954: Property p = base.createProperty(NS + "p");
0955: i.addProperty(p, "foo");
0956:
0957: // Inf model
0958: List rules = Rule.parseRules("(?x eg:p ?y) -> (?x eg:q ?y). ");
0959: GenericRuleReasoner reasoner = new GenericRuleReasoner(rules);
0960: InfModel infModel = ModelFactory.createInfModel(reasoner, base);
0961:
0962: TestListener listener = new TestListener();
0963: infModel.getDeductionsModel().register(listener);
0964: infModel.rebind();
0965: infModel.prepare();
0966: assertEquals("foo", listener.getLastValue());
0967:
0968: i.removeAll(p);
0969: i.addProperty(p, "bar");
0970: infModel.rebind();
0971: infModel.prepare();
0972: assertEquals("bar", listener.getLastValue());
0973: }
0974:
0975: /**
0976: * Listener class used in testing. Decects (* eg:q ?l) patterns
0977: * and notes the last value of ?l seen and returns it as a literal string.
0978: */
0979: private class TestListener extends StatementListener {
0980: final Property Q = ResourceFactory
0981: .createProperty(PrintUtil.egNS + "q");
0982: RDFNode lastValue = null;
0983:
0984: public Object getLastValue() {
0985: if (lastValue != null && lastValue.isLiteral()) {
0986: return ((Literal) lastValue).getLexicalForm();
0987: } else {
0988: return lastValue;
0989: }
0990: }
0991:
0992: public void addedStatement(Statement s) {
0993: if (s.getPredicate().equals(Q)) {
0994: lastValue = s.getObject();
0995: }
0996: }
0997: }
0998:
0999: /**
1000: * Problems with getDeductionsModel not rerunning prepare at OntModel level
1001: */
1002: public void testOntModelGetDeductions() {
1003: List rules = Rule
1004: .parseRules("(?x rdfs:subClassOf ?y) (?i rdf:type ?x) -> (?i rdf:type ?y).");
1005: GenericRuleReasoner reasoner = new GenericRuleReasoner(rules);
1006: OntModelSpec spec = new OntModelSpec(OntModelSpec.OWL_MEM);
1007: spec.setReasoner(reasoner);
1008: OntModel om = ModelFactory.createOntologyModel(spec);
1009: OntClass A = om.createClass(PrintUtil.egNS + "A");
1010: OntClass B = om.createClass(PrintUtil.egNS + "B");
1011: OntResource i = om.createOntResource(PrintUtil.egNS + "i");
1012: A.addSuperClass(B);
1013: i.addRDFType(A);
1014: Model deductions = om.getDeductionsModel();
1015: i.removeRDFType(A);
1016: deductions = om.getDeductionsModel();
1017: assertFalse("Deductions model updating correctly", deductions
1018: .contains(i, RDF.type, B));
1019: }
1020:
1021: /**
1022: * Builtin which just records whether it has been called.
1023: * Used in implementing testGroundClosure.
1024: */
1025: private static class Flag extends BaseBuiltin {
1026: public String getName() {
1027: return "flag";
1028: }
1029:
1030: public boolean fired = false;
1031:
1032: public boolean bodyCall(Node[] args, int length,
1033: RuleContext context) {
1034: fired = true;
1035: return true;
1036: }
1037: }
1038:
1039: // debug assistant
1040: // private void tempList(Model m, Resource s, Property p, RDFNode o) {
1041: // System.out.println("Listing of " + PrintUtil.print(s) + " " + PrintUtil.print(p) + " " + PrintUtil.print(o));
1042: // for (StmtIterator i = m.listStatements(s, p, o); i.hasNext(); ) {
1043: // System.out.println(" - " + i.next());
1044: // }
1045: // }
1046:
1047: }
1048:
1049: /*
1050: (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
1051: All rights reserved.
1052:
1053: Redistribution and use in source and binary forms, with or without
1054: modification, are permitted provided that the following conditions
1055: are met:
1056:
1057: 1. Redistributions of source code must retain the above copyright
1058: notice, this list of conditions and the following disclaimer.
1059:
1060: 2. Redistributions in binary form must reproduce the above copyright
1061: notice, this list of conditions and the following disclaimer in the
1062: documentation and/or other materials provided with the distribution.
1063:
1064: 3. The name of the author may not be used to endorse or promote products
1065: derived from this software without specific prior written permission.
1066:
1067: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1068: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1069: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1070: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1071: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1072: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1073: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1074: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1075: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1076: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1077: */
|