shexjs / shex.js

shex.js javascript package
MIT License
60 stars 17 forks source link

ShEx Loader + Validator example in Readme is broken #50

Closed micgro42 closed 5 years ago

micgro42 commented 5 years ago

The example given in the Readme for how to use the Loader and Validator, seems broken. It throws the following error:

Uncaught (in promise) TypeError: db.getNeighborhood is not a function
    at ShExValidator_constructor._validateShape (shex-webapp-webpack.js:51591)
    at ShExValidator_constructor._validateShapeExpr (shex-webapp-webpack.js:51539)
    at ShExValidator_constructor.validate (shex-webapp-webpack.js:51505)
    at shex-test.html:19

It seems to be thrown at https://github.com/shexSpec/shex.js/blob/17756428852d9abb1d5242f539675265ea38395a/packages/shex-core/lib/ShExValidator.js#L474

I also receive this error in the version build with the npm package, where it is thrown at https://github.com/shexSpec/shex.js/blob/6709a8dc8ca9e19397aeea52cc898ec2e31d6cb7/packages/shex-core/lib/ShExValidator.js#L583

You can reproduce this by putting the following html file next to shex-simple.html in packages/shex-webapp/doc/ and opening it.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Minimal failing example</title>
</head>
<body>
<script src="../browser/shex-webapp-webpack.js"></script>
<script>

    var shex = ShExWebApp; // @@ rename globally
    var shexc = "http://shex.io/examples/Issue.shex";
    var shape = "http://shex.io/examples/IssueShape";
    var data = "http://shex.io/examples/Issue1.ttl";
    var node = "http://shex.io/examples/Issue1";

    shex.Loader.load([shexc], [], [data], []).then(function (loaded) {
        console.log(shex.Validator.construct(loaded.schema).validate(loaded.data, node, shape));
    });
</script>
</body>
</html>

Am I doing something wrong?

ericprud commented 5 years ago

You need to have shex.Util.makeN3DB(loaded.data) around "loaded.data". This returns a wrapper around the triple store with a function called getNeighborhood(). Since this is no longer specific to N3.js, I need a better name for that function. N3.js now follows the RDFJS dataset spec so maybe a better name is makeDataset(db). Something like fromDataset(db) would look good from a literate programming perspective but wouldn't really say what it does. Advice?

micgro42 commented 5 years ago

Thanks, I will have a closer look at this tonight or over the coming days.

Unfortunately, my knowledge of this domain is very limited. But I will try to see if one of the names feels more intuitive to me :)

micgro42 commented 5 years ago

Greetings from the Wikimedia Hackathon in Prague 👋

Thank you for your advice above, with that extra call it isn't throwing any errors anymore. But the validation results are still wrong :/

In the example below, I have a schema that verifies

  1. that the item is instance of house cat
  2. that the item has a birthday property

It is provided with the data for the cat Toffee, which should pass that validation (see simple shex evaluation). But it gives a failure that the two properties are missing. It feels like I still miss a call to add the triples (quads?) to the data before it is validated. Any advice?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Minimal failing example</title>
</head>
<body>
<script src="../browser/shex-webapp-webpack.js"></script>
<script>

    var shex = ShExWebApp; // @@ rename globally
    var shexc = "https://wikidata-shex.wmflabs.org/wiki/Special:EntitySchemaText/E3";
    var shape = "https://wikidata-shex.wmflabs.org/wiki/Special:EntitySchemaText/wikidata-cat";
    var data = "https://www.wikidata.org/wiki/Special:EntityData/Q49581026.ttl";
    var node = "https://www.wikidata.org/wiki/Special:EntityData/Q49581026";

    shex.Loader.load([shexc], [], [data], []).then(function (loaded) {
        const db = shex.Util.makeN3DB(loaded.data);
        console.log(shex.Validator.construct(loaded.schema).validate(db, node, loaded.schema.start));
    });
</script>
</body>
</html>

About the naming: It should include what is made and maybe also from what (since there are no types): makeXFromY(...). Also, don't be concerned about the length of the name. Better a bit longer and explicit than short and too cryptic. This is especially true as the method name is currently the only documentation that there is for the API. That being said, the examples in the readme is quite useful. Once we get it working I'll make a PR to update the docs :)

micgro42 commented 5 years ago

Got it via stepping through the code with the debugger in parallel and looking at what is going on. The following HTML gives the correct results:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Minimal failing example</title>
</head>
<body>
<script src="../browser/shex-webapp-webpack.js"></script>
<script>
    var shex = ShExWebApp; // @@ rename globally
    var shexc = "https://wikidata-shex.wmflabs.org/wiki/Special:EntitySchemaText/E3";
    var shape = "https://wikidata-shex.wmflabs.org/wiki/Special:EntitySchemaText/wikidata-cat";
    var data = "https://www.wikidata.org/wiki/Special:EntityData/Q49581026.ttl";
    var node = "http://www.wikidata.org/entity/Q49581026";

    shex.Loader.load([shexc], [], [data], []).then(function (loaded) {
        const db = shex.Util.makeN3DB(loaded.data);
        const validator = shex.Validator.construct(loaded.schema, { results: "api" });
        const result = validator.validate(db, [{node, shape: shex.Validator.start}]);
        console.log(result);
    });
</script>
</body>
</html>

🙌

That being said, I still don't fully understand why it works. Especially, the significance of the changed node url is totally not clear to me. But anyway, this should get me going with my actual project 😀 Tomorrow, I'll make a pull request to update the Readme as promised.