carml / carml

A pretty sweet RML engine, for RDF.
MIT License
100 stars 20 forks source link

Only first JSON object of stream gets mapped #37

Open pheyvaer opened 6 years ago

pheyvaer commented 6 years ago

Hi,

I'm trying to run the following mapping on a stream.

@prefix rr: <http://www.w3.org/ns/r2rml#>.
@prefix rml: <http://semweb.mmlab.be/ns/rml#>.
@prefix ex: <http://example.com/>.
@prefix ql: <http://semweb.mmlab.be/ns/ql#> .
@prefix carml: <http://carml.taxonic.com/carml/> .

<#SubjectMapping> a rr:TriplesMap;
        rml:logicalSource [
                rml:source [
                        a carml:Stream;
                        carml:streamName "input";
                ];
                rml:referenceFormulation ql:JSONPath;
                rml:iterator "$"
        ];

        rr:subjectMap [
                rr:template "http://example.com/Child/{id}";
                rr:class ex:Child
        ];

        rr:predicateObjectMap [
                rr:predicate ex:loves;
                rr:objectMap [
                        rml:reference "name";
                ]
].

I send the following JSON objects (3 in this example) separately to a socket on localhost:5005.

{"id":"test", "name":"John"}
{"id":"tests"}
{"id":"tests"}

In my Java code I do the following;

 try {
            Set<TriplesMap> mapping =
                    RmlMappingLoader
                            .build()
                            .load(Paths.get(args[0]), RDFFormat.TURTLE);

            RmlMapper mapper = RmlMapper.newBuilder().build();
            Socket echoSocket = new Socket("localhost", 5005);
            mapper.bindInputStream("input", echoSocket.getInputStream());

            Model result = mapper.map(mapping);

            for (Statement statement: result) {
                System.out.println(statement);
            }

        } catch (Exception e){
            System.out.println(e);
        }

In the model I see that only the first JSON object is mapped. However, the 2 following ones are not. Do you have any idea why this happens?

pmaria commented 6 years ago

@pheyvaer trying your mapping without the socket setup seems to work for me when using the other JSON object

        String source =
                "{\"id\":\"tests\"}";
        InputStream inputStream = IOUtils.toInputStream(source);

        RmlMapper mapper = RmlMapper.newBuilder().build();
        mapper.bindInputStream("input", inputStream);

        String mappingString = 
            "@prefix rr: <http://www.w3.org/ns/r2rml#>.\r\n" + 
            "@prefix rml: <http://semweb.mmlab.be/ns/rml#>.\r\n" + 
            "@prefix ex: <http://example.com/>.\r\n" + 
            "@prefix ql: <http://semweb.mmlab.be/ns/ql#> .\r\n" + 
            "@prefix carml: <http://carml.taxonic.com/carml/> .\r\n" + 
            "\r\n" + 
            "<#SubjectMapping> a rr:TriplesMap;\r\n" + 
            "        rml:logicalSource [\r\n" + 
            "                rml:source [\r\n" + 
            "                        a carml:Stream;\r\n" + 
            "                        carml:streamName \"input\";\r\n" + 
            "                ];\r\n" + 
            "                rml:referenceFormulation ql:JSONPath;\r\n" + 
            "                rml:iterator \"$\"\r\n" + 
            "        ];\r\n" + 
            "\r\n" + 
            "        rr:subjectMap [\r\n" + 
            "                rr:template \"http://example.com/Child/{id}\";\r\n" + 
            "                rr:class ex:Child\r\n" + 
            "        ];\r\n" + 
            "\r\n" + 
            "        rr:predicateObjectMap [\r\n" + 
            "                rr:predicate ex:loves;\r\n" + 
            "                rr:objectMap [\r\n" + 
            "                        rml:reference \"name\";\r\n" + 
            "                ]\r\n" + 
            "].";

        InputStream mappingStream = IOUtils.toInputStream(mappingString);

        Set<TriplesMap> mapping =
            RmlMappingLoader
                .build()
                .load(mappingStream, RDFFormat.TURTLE);

        Model result = mapper.map(mapping);

        result.forEach(System.out::println);

results in <http://example.com/Child/tests> a <http://example.com/Child> .

pheyvaer commented 6 years ago

But what happens with multiple objects then? In my case, the first object got also mapped. It were the following that didn't work.

pmaria commented 6 years ago

Ah sorry, I misinterpreted.

Int it's current state CARML doesn't support listening to input streams yet (mainly because we didn't have that usecase yet), Currently only "static" inputstreams are supported, in the sense that it reads all of the stream and maps it, when map() is called.

We would like to add support at some point though. Would welcome any contribution.

pmaria commented 6 years ago

@pheyvaer For now it is of course possible to have a separate process listenening to the socket and passing any new input to an existing mapper instance. Hope that helps.