Re: parsing and matching triples
That's a great idea. +1 From: ajs6fSent: Tuesday, May 8, 2018 10:55 AM To: dev@jena.apache.org Subject: Re: parsing and matching triples Forking a thread off to dev@: Do we have a global policy about where null is accepted as a wildcard? I know it works in at least some places... I would love to (over an appropriate period of time and with lots of warnings and deprecation and so forth) stop letting it be a wildcard and require code to use the actual wildcard objects. ajs6f > On May 8, 2018, at 11:51 AM, Andy Seaborne wrote: > > Barry, > > As a general concept "matching" happens at different levels. > > Triple.match corresponds to the matching done by Graph.find - RDF terms (URI, > bnode, literal) match exactly, and Node.ANY is a wildcard. > > Triple t1 = Triple.ANY; > Triple t2 = SSE.parseTriple("(:s :p :o)"); > t1.matches(t2) -> true > t2.matches(t1) -> false > > Variables are a concept for SPARQL - and matches usefully need to return > which variable matched which RDF Term. > > Triple patterns match against graphs and return an iterator of ways they > match. > > Consider cases like "?x ?p ?x" where the variables impose am additional shape. > > If you want variable bindings, you could build a SPARQL query or wrap up some > of the internal code e.g. > > /** Evaluate a triple pattern */ > private static QueryIterator match(Graph source, Triple pattern) { >ExecutionContext execContext = > new ExecutionContext(ARQ.getContext(), source, null, null) ; >QueryIterator chain = QueryIterRoot.create(execContext) >chain = new QueryIterTriplePattern(chain, pattern, execContext) ; >return chain ; > } > >Andy > > On 08/05/18 09:21, Nouwt, B. (Barry) wrote: >> Hi everybody, >> I’m trying to reuse Apache Jena code that parses and matches triples. I’m >> currently looking at the SSE class’s parseTriple() method. This seems to fit >> my purpose for parsing a string representation of a triple into a triple >> object. I also noticed the following Javadoc on the Node.maches(Node) method: >> Answer true iff this node accepts the other one as a match. >> The default is an equality test; it is over-ridden in subclasses to >> provide the appropriate semantics for literals, ANY, and variables. >> Since this is exactly what I’m looking for, I’ve tried to match two triples >> using the matches() method, but it does not seem to work: >> Triple t1 = SSE.parseTriple("(?s ?p ?o)"); >> Triple t2 = SSE.parseTriple("(test:subject test:predicate test:object)", pm); >> t1.matches(t2) >> The final statement returns false, while I would expect it to return true. >> Either, I’m missing something (which is completely realistic ), or I should >> use some other method to match two triples in the way described above. >> Any help is appreciated! >> Regards, Barry >> This message may contain information that is not intended for you. If you >> are not the addressee or if this message was sent to you by mistake, you are >> requested to inform the sender and delete the message. TNO accepts no >> liability for the content of this e-mail, for the manner in which you use it >> and for damage of any kind resulting from the risks inherent to the >> electronic transmission of messages.
Re: Dataset.getUnionModel()
Hi Andy, We are using the general dataset. Our use case is simply that we are taking quads in from clients, which may or may not include a default graph. We use the union model for several things, but one example is SHACL validation. So we always need to remember to include the default graph into the union model. Currently, I've subclassed the DatasetImpl to override the unionModel() method; but it sounds like we may be an edge case. Thanks, -Adam From: Andy Seaborne <a...@apache.org> Sent: Saturday, April 14, 2018 5:01 PM To: dev@jena.apache.org Subject: Re: Dataset.getUnionModel() Hi Adam, Yes, the union model is the graph union of the named graphs and does not include the default graph. This choice is intentional and is driven by the SPARQL side of things. It's a useful way to have manageability of the data by using the SPARQL Graph Store Protocol to PUT and POST graphs that together make the default graph to be queried. This matches the behaviour some other triple stores. Which kind of dataset are you using? For the general dataset that can include any models, a graph can be added twice so the default graph can be added as named graph as well and so included in the union. What is your application usage that naturally wanted the default model to be included? Andy On 14/04/18 21:00, Adam Jacobs wrote: > Dataset.getUnionModel() excludes the default graph. > Would it be appropriate to include the default graph in this method, or to > add an additional unioning method to the Dataset interface which includes the > default graph? > It seems like an oversight, but maybe there was a reason for excluding it? >
Dataset.getUnionModel()
Dataset.getUnionModel() excludes the default graph. Would it be appropriate to include the default graph in this method, or to add an additional unioning method to the Dataset interface which includes the default graph? It seems like an oversight, but maybe there was a reason for excluding it?
[jira] [Comment Edited] (JENA-1499) The TIM dataset retains a memory of named graphs after deleting all quads.
[ https://issues.apache.org/jira/browse/JENA-1499?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16388781#comment-16388781 ] Adam Jacobs edited comment on JENA-1499 at 3/7/18 12:43 AM: >From the API side, I've noticed empty graphs are consistently treated as >"unimportant" and are often created superfluously. {code:java} Dataset ds = DatasetFactory.create(); ds.containsNamedModel("foo"); ds.removeNamedModel("bar"); Iterator iterator = ds.listNames(); System.out.println(iterator.next()); System.out.println(iterator.next());{code} As mentioned, this is significant when serializing to TRIG. was (Author: jaco0646): >From the API side, I've noticed empty graphs are consistently treated as >"unimportant" and are often created superfluously. {{Dataset ds = DatasetFactory.create();}} {{ds.containsNamedModel("foo");}} {{ds.removeNamedModel("bar");}} {{Iterator iterator = ds.listNames();}} {{System.out.println(iterator.next());}} {{System.out.println(iterator.next());}} As mentioned, this is significant when serializing to TRIG. > The TIM dataset retains a memory of named graphs after deleting all quads. > -- > > Key: JENA-1499 > URL: https://issues.apache.org/jira/browse/JENA-1499 > Project: Apache Jena > Issue Type: Bug >Affects Versions: Jena 3.6.0 >Reporter: Andy Seaborne >Priority: Major > > Illustration: > {noformat} > DatasetGraph dsg = DatasetGraphFactory.createTxnMem(); > Quad q = SSE.parseQuad("(:g :s :p :o)"); > dsg.add(q); > dsg.delete(q); > Iter.print(dsg.listGraphNodes()); > {noformat} > prints {{http://example/g}}. -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Commented] (JENA-1499) The TIM dataset retains a memory of named graphs after deleting all quads.
[ https://issues.apache.org/jira/browse/JENA-1499?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16388781#comment-16388781 ] Adam Jacobs commented on JENA-1499: --- >From the API side, I've noticed empty graphs are consistently treated as >"unimportant" and are often created superfluously. {{Dataset ds = DatasetFactory.create();}} {{ds.containsNamedModel("foo");}} {{ds.removeNamedModel("bar");}} {{Iterator iterator = ds.listNames();}} {{System.out.println(iterator.next());}} {{System.out.println(iterator.next());}} As mentioned, this is significant when serializing to TRIG. > The TIM dataset retains a memory of named graphs after deleting all quads. > -- > > Key: JENA-1499 > URL: https://issues.apache.org/jira/browse/JENA-1499 > Project: Apache Jena > Issue Type: Bug >Affects Versions: Jena 3.6.0 >Reporter: Andy Seaborne >Priority: Major > > Illustration: > {noformat} > DatasetGraph dsg = DatasetGraphFactory.createTxnMem(); > Quad q = SSE.parseQuad("(:g :s :p :o)"); > dsg.add(q); > dsg.delete(q); > Iter.print(dsg.listGraphNodes()); > {noformat} > prints {{http://example/g}}. -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Commented] (JENA-1391) Add Convenience Methods to Dataset
[ https://issues.apache.org/jira/browse/JENA-1391?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16382936#comment-16382936 ] Adam Jacobs commented on JENA-1391: --- This looks fine to me. Nice work. > Add Convenience Methods to Dataset > -- > > Key: JENA-1391 > URL: https://issues.apache.org/jira/browse/JENA-1391 > Project: Apache Jena > Issue Type: Improvement > Components: ARQ >Affects Versions: Jena 3.4.0 > Reporter: Adam Jacobs >Assignee: A. Soroka >Priority: Trivial > > The Dataset interface could provide several convenience methods similar to > the Model interface, allowing usability of RDF quads on par with RDF triples. > Specific examples include, > # add(Dataset) > # remove(Dataset) > # union(Dataset) > # intersection(Dataset) > # difference(Dataset) > # isEmpty() > Following is a possible implementation of these methods. > {code:java} > default Dataset add(Dataset d) { > this.getDefaultModel().add(d.getDefaultModel()); > d.listNames().forEachRemaining(name -> > this.getNamedModel(name).add(d.getNamedModel(name))); > return this; > } > default Dataset remove(Dataset d) { > this.getDefaultModel().remove(d.getDefaultModel()); > d.listNames().forEachRemaining(name -> > this.getNamedModel(name).remove(d.getNamedModel(name))); > return this; > } > default Dataset union(Dataset d) { > return DatasetFactory.create().add(this).add(d); > } > default Dataset difference(Dataset d) { > Dataset output = DatasetFactory.create(); > > output.setDefaultModel(this.getDefaultModel().difference(d.getDefaultModel())); > this.listNames().forEachRemaining(name -> { > Model difference = > this.getNamedModel(name).difference(d.getNamedModel(name)); > if (!difference.isEmpty()) output.addNamedModel(name, difference); > }); > return output; > } > default Dataset intersection(Dataset d) { > Dataset output = DatasetFactory.create(); > > output.setDefaultModel(this.getDefaultModel().intersection(d.getDefaultModel())); > Set names = this.names(); > names.retainAll(d.names()); > names.forEach(name -> { > Model intersection = > this.getNamedModel(name).intersection(d.getNamedModel(name)); > if (!intersection.isEmpty()) output.addNamedModel(name, > intersection); > }); > return output; > } > default Set names() { > Set names = new HashSet<>(); > this.listNames().forEachRemaining(names::add); > return names; > } > default boolean isEmpty() { > return this.asDatasetGraph().isEmpty(); > } > {code} -- This message was sent by Atlassian JIRA (v7.6.3#76005)
[jira] [Created] (JENA-1495) Covariant return type for Model's PrefixMapping methods.
Adam Jacobs created JENA-1495: - Summary: Covariant return type for Model's PrefixMapping methods. Key: JENA-1495 URL: https://issues.apache.org/jira/browse/JENA-1495 Project: Apache Jena Issue Type: Improvement Components: Core Affects Versions: Jena 3.6.0 Reporter: Adam Jacobs The {{Model}} interface inherits several methods from {{PrefixMapping}} which return {{this}}. The return type of these methods can be refined to allow call chaining with the {{Model}} object. There appear to be two concrete implementations of {{Model}} which override the {{PrefixMapping}} methods: {{ModelCom}} and {{SecuredModelImpl}}. Steps to add covariant return types for prefix mapping are as follows. Add these six methods to the Model interface. # Model setNsPrefix( String prefix, String uri ); # Model removeNsPrefix( String prefix ); # Model clearNsPrefixMap(); # Model setNsPrefixes( PrefixMapping other ); # Model setNsPrefixes( Map<String, String> map ); # Model withDefaultMappings( PrefixMapping map ); ...and update ModelCom accordingly. Add these six methods to the SecuredModel interface. # SecuredModel setNsPrefix( String prefix, String uri ); # SecuredModel removeNsPrefix( String prefix ); // This method is already defined. # SecuredModel clearNsPrefixMap(); # SecuredModel setNsPrefixes( PrefixMapping other ); # SecuredModel setNsPrefixes( Map<String, String> map ); # SecuredModel withDefaultMappings( PrefixMapping map ); ...and update SecuredModelImpl accordingly. -- This message was sent by Atlassian JIRA (v7.6.3#76005)
Re: JsonLD @vocab
Do you know where jsonld discussions are at? I'm having trouble finding a mailing list. From: Andy Seaborne <a...@apache.org> Sent: Thursday, January 4, 2018 2:34 PM To: dev@jena.apache.org Subject: Re: JsonLD @vocab Adam, In the first instance, this seems like something to raise with the jsonld-java team to find out if that is intentional. Could you open a discussion issue there? IIRC empty prefix and the base are mixed up in JSON-LD. Andy On 04/01/18 03:34, Adam Jacobs wrote: > The @vocab prefix is dropped by Jena when parsing JsonLD. > An empty prefix is correctly translated into @vocab during serialization, but > is lost during deserialization. > Below code demonstrates the point. > > public static void main(String... args) { > String base = "http://www.ns.com/base/;; > String prefix = "http://www.ns.com/prefix/;; > > Model m = ModelFactory.createDefaultModel(); > m.setNsPrefix("", base); > m.setNsPrefix("prefix", prefix); > > m.add(m.createResource(base + "foo"), m.createProperty(prefix + > "bar"), m.createResource(base + "baz")); > String jsonLD = serializeJsonLD(m); > System.out.println(jsonLD); > > InputStream in = new ByteArrayInputStream(jsonLD.getBytes()); > Model m2 = ModelFactory.createDefaultModel().read(in, null, > "jsonld"); > System.out.println(serializeJsonLD(m2)); > } > > public static String serializeJsonLD(Model m) { > OutputStream out = new ByteArrayOutputStream(); > m.write(out, "jsonld"); > return out.toString(); > } > > From what I can see, jsonld-java is intentionally ignoring the @vocab key at > line 277 of Context.java. > > https://github.com/jsonld-java/jsonld-java/blob/master/core/src/main/java/com/github/jsonldjava/core/Context.java > > I'm not sure if this is a bug in jsonld-java, or intentional behavior from a > jsonld perspective that Jena should work around e.g. in JsonLDReader? >
Re: PROV vocabulary class
Is it a good idea to have a public mutable model? From: Cotton FranckSent: Sunday, January 7, 2018 11:47 AM To: dev@jena.apache.org Subject: RE:PROV vocabulary class Hi Adam. Here: https://gist.github.com/FranckCo/889d1f137dc412ceab214159a49375e2 Franck De : ajs6f [aj...@apache.org] Envoyé : dimanche 7 janvier 2018 18:07 À : dev@jena.apache.org Objet : Re: PROV vocabulary class This list doesn't permit attachments. Can you please send your work as a PR on Github, or failing that, as a gist or pastebin or the like? Adam Soroka > On Jan 7, 2018, at 12:00 PM, Cotton Franck wrote: > > Hello > > For my own needs, I created this class corresponding to the W3C PROV > vocabulary. It could fit in the org.apache.jena.vocabulary package. Please > fill free to add the relevant license text, I don't claim any IP on the class. > > Cheers > Franck
JsonLD @vocab
The @vocab prefix is dropped by Jena when parsing JsonLD. An empty prefix is correctly translated into @vocab during serialization, but is lost during deserialization. Below code demonstrates the point. public static void main(String... args) { String base = "http://www.ns.com/base/;; String prefix = "http://www.ns.com/prefix/;; Model m = ModelFactory.createDefaultModel(); m.setNsPrefix("", base); m.setNsPrefix("prefix", prefix); m.add(m.createResource(base + "foo"), m.createProperty(prefix + "bar"), m.createResource(base + "baz")); String jsonLD = serializeJsonLD(m); System.out.println(jsonLD); InputStream in = new ByteArrayInputStream(jsonLD.getBytes()); Model m2 = ModelFactory.createDefaultModel().read(in, null, "jsonld"); System.out.println(serializeJsonLD(m2)); } public static String serializeJsonLD(Model m) { OutputStream out = new ByteArrayOutputStream(); m.write(out, "jsonld"); return out.toString(); } >From what I can see, jsonld-java is intentionally ignoring the @vocab key at >line 277 of Context.java. https://github.com/jsonld-java/jsonld-java/blob/master/core/src/main/java/com/github/jsonldjava/core/Context.java I'm not sure if this is a bug in jsonld-java, or intentional behavior from a jsonld perspective that Jena should work around e.g. in JsonLDReader?
[jira] [Commented] (JENA-1452) Special case GraphUnionRead for one graph.
[ https://issues.apache.org/jira/browse/JENA-1452?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16299446#comment-16299446 ] Adam Jacobs commented on JENA-1452: --- It looks like {{TestGraphUnionRead}} only covers the {{find()}} method. What is the expectation when {{add()}}, {{delete()}}, etc. are called on this graph? Is the behavior of those methods consistent for this special case? > Special case GraphUnionRead for one graph. > -- > > Key: JENA-1452 > URL: https://issues.apache.org/jira/browse/JENA-1452 > Project: Apache Jena > Issue Type: Improvement >Affects Versions: Jena 3.6.0 >Reporter: Andy Seaborne >Assignee: Andy Seaborne >Priority: Minor > Fix For: Jena 3.7.0 > > -- This message was sent by Atlassian JIRA (v6.4.14#64029)
Re: potential new API Was: Immutability
I just want to mention that it was not my intent to derail progress on Jena-1391 (https://issues.apache.org/jira/browse/JENA-1391) by raising the issue of immutability, particularly if immutability would be implemented via a new API. I don't think it should be considered a blocker to that story. Apologies if I threw a wrench into the plan. From: ajs6fSent: Wednesday, December 13, 2017 10:39 AM To: dev@jena.apache.org Subject: potential new API Was: Immutability Yes, the SPI is likely fine, or we will find out otherwise if we try a new API. :) A new API is clearly no small thing. I suppose one way to approach the thing would be to look at what Clerezza and RDF4J 4 and Commons RDF have come up with, what worked and what didn't, and then bring in our own use cases and ideas... The two "asks" I've heard recently from Jena users are: immutability and Streams. I'm guessing there are others. I would like to take advantage of Optional for some of the attributes of a node (e.g. return the lang of a literal as Optional). Other thoughts? It's fun to make wish lists at the end of the year. :grin: ajs6f > On Nov 16, 2017, at 11:47 AM, Andy Seaborne wrote: > > Yes, I think it is best done as a new API. > > Modifications to the existing one are likely to run into problems somewhere > and given the number of users, and the change over time on upgrades, having > compatibility matters as does gradual migration > > A complicates case: Dataset.getModel(String) returns a model. No idea whether > it is immutable or not or how it will be used. Assigning to a ImmutableModel > does not guaratee anything - it helps the caller not make mistakes but the > model is not immutable. Some code calling getModel can change it. And the > union model isn't immutable! - it's a dynamic union and any name graph change > will be reflected. The world is multithreaded. > > But the main reason for a new API is that this is just one of several > features to include so to make it a success these different features need to > come together into one *agreed* design. > > The good news is that it can target the SPI. > (I see no value in changing the SPI for this - that's not it's role) > > ARQ's API is really very small. A design that took a dataset+model view of > the world would be a good thing. > >Andy > > See also commons-rdf. > That is RDF 1.1 compliant > > On 15/11/17 15:52, aj...@apache.org wrote: >> So it seems to me that if we want to introduce immutable types, we might >> want to do that in the context of a completely new API. The use of the Java >> 8 Streams API is also something that has been mooted as something that might >> merit a new Jena API. (Instead of mixing things up in the current one.) >> I'm not sure how that plays out with ARQ, though. We would want people to be >> able to use the new types with ARQ without much difficulty.
Re: Jena-1427 - nextOptional()
Note that the original request in Jena-1427 was for a nextOrElse() method accepting an instance of Supplier. The implementation of nextOptional(), released in version 3.6, solves my use case just as well. The only reason I had not requested nextOptional() directly is that ExtendedIterator was already composed of custom functional-programming-oriented methods. In my experience, the API of ExtendedIterator is superior (i.e. more user friendly) than what Java 8 offers in its Streams, so I thought it was worth considering alternatives. For me, there is no wrong choice here as any of several options solve my problem. I appreciate everyone who has contributed to the discussion. From: ajs6fSent: Sunday, December 17, 2017 1:28 PM To: dev@jena.apache.org Subject: Re: Jena-1427 - nextOptional() > On Dec 17, 2017, at 2:18 PM, Claude Warren wrote: > It seems that much of the rest of the discussion is covered by adding a > method to convert the iterator to a stream (probably just a call to an > existing Java method. Just to this point alone-- this is something that came up _in_ the discussion (we even already have Iter::asStream for the purpose), and I don't agree with it. Converting an iterator to a stream is a useful thing, to be sure, but although it doesn't really speak to the optimizations that people (rightly) associate with a stream (i.e. it doesn't push filters or other computations back to whatever they might look like closer to the source of elements) it does create a bunch of objects and machinery. I'd rather not encourage people to do this-- I'd rather encourage them to use plain iterators unless/until we can actually supply an API with real streams. Otherwise: > Perhaps we should add a next( T default ) method that will return the default > if hasNext() returns false. This seem better than polluting the environment > with Optionals that don't really belong. I don't agree at all that Optional doesn't belong here, but if the original requestor can confirm that this would meet the use case, and if we can come up with something for throwing a custom exception that does pass Claude's "smell test", then I'm fine with it. I'd rather not add method after method to ExtendedIterator for every possible syntactic convenience. (This ain't Scala! :wink:) ajs6f > On Dec 17, 2017, at 2:18 PM, Claude Warren wrote: > > From the original request it seems the requirements were: > 1. return a default value if the iterator is empty. > 2. throw a custom exception if the iterator is empty. > > > Perhaps we should add a next( T default ) method that will return the > default if hasNext() returns false. This seem better than polluting the > environment with Optionals that don't really belong. > > If we want to provide a method to throw an custom exception we could add > something like next( Class e ) to create and throw the > exception. But I don't like this one for some reason. Like the Optional > it doesn't pass the smell test for me. > > It seems that much of the rest of the discussion is covered by adding a > method to convert the iterator to a stream (probably just a call to an > existing Java method. > > Claude > > > On Sun, Dec 17, 2017 at 5:50 PM, Andy Seaborne wrote: > >> We seem to have drifted a bit here - the original use case wasn't about >> streaming as I read it. list* get used to write zero/one tests and one/many >> tests dealing with properties etc. >> >> And, of course, we want to avoid the anti-pattern of Optional/if-empty. >> >> Claude - thoughts on the use case? How might we evolve the current API >> without method bloat? >> >>Andy >> >> >> On 14/12/17 17:46, Claude Warren wrote: >> >>> I was expecting that with the discovery that optional throws a null >>> pointer >>> exception when the retrieved value is null would be enough to remove this >>> functionality. >>> >>> I am concerned that once added it will be difficult to remove and that its >>> operation is not congruent with stream based optional usage. >>> >>> Claude >>> >>> On 14 Dec 2017 10:33, "Andy Seaborne" wrote: >>> >>> Claude, The JIRA ticket ends: [[ ASF GitHub Bot added a comment - 04/Dec/17 15:36 That was already the case in the PR and I've added text to call it out explicitly into the javadoc. githubbot ASF GitHub Bot added a comment - 04/Dec/17 15:40 Github user ajs6f commented on the issue: https://github.com/apache/jena/pull/323 Okay, that works for me! Andy Seaborne added a comment - 04/Dec/17 15:58 nextOptional added for release 3.6.0. Proposal: close this JIRA for now, see how nextOptional works out and revisit orElse* based on experience. ajs6f A. Soroka added a comment - 1 week ago +1 ]] Adding
[jira] [Created] (JENA-1451) DatasetFactory.createGeneral() never contains default graph
Adam Jacobs created JENA-1451: - Summary: DatasetFactory.createGeneral() never contains default graph Key: JENA-1451 URL: https://issues.apache.org/jira/browse/JENA-1451 Project: Apache Jena Issue Type: Bug Components: ARQ Affects Versions: Jena 3.6.0 Reporter: Adam Jacobs Priority: Minor See: http://mail-archives.apache.org/mod_mbox/jena-dev/201712.mbox/<0a67c2ce-f414-3eae-51dc-226768d4facd%40apache.org> Model m1 = ModelFactory.createDefaultModel(); m1.add(m1.createResource(), m1.createProperty("foo"), m1.createResource()); Dataset memory = DatasetFactory.create(); Dataset general = DatasetFactory.createGeneral(); memory.getDefaultModel().add(m1); general.getDefaultModel().add(m1); //Memory model contains default graph. General model does not. System.out.println(memory.containsNamedModel(Quad.defaultGraphIRI.getURI())); //true System.out.println(general.containsNamedModel(Quad.defaultGraphIRI.getURI())); //false -- This message was sent by Atlassian JIRA (v6.4.14#64029)
DatasetFactory.createGeneral()
I've noticed a couple of differences between DatasetFactory.create() and DatasetFactory.createGeneral(). My understanding is that the former is intended to create deep copies of its graphs whereas the latter maintains shallow links. The DatasetFactory has quite a few creational methods, and their documentation tends to be brief; but a couple of behaviors stood out to me. 1. In the general dataset, containsNamedModel() always returns false for the default graph. This seems unexpected whether from the perspective of copies or links. 2. In the general dataset, addNamedModel() appears to perform the same function as replaceNamedModel(). This is understandable for simplicity; but from the memory dataset perspective, a combined view of identically-named graphs would be expected. ~ Fun with words: can we say that "identically-named graphs" are homonymous? ;) ~ Following is some code demonstrating the two points above. Are these behaviors intentional? public static void main(String... args) { Model m1 = ModelFactory.createDefaultModel(); m1.add(m1.createResource(), m1.createProperty("foo"), m1.createResource()); Model m2 = ModelFactory.createDefaultModel(); m2.add(m2.createResource(), m2.createProperty("bar"), m2.createResource()); Dataset memory = DatasetFactory.create(); Dataset general = DatasetFactory.createGeneral(); memory.getDefaultModel().add(m1); general.getDefaultModel().add(m1); memory.addNamedModel("bar", m2); general.addNamedModel("bar", m2); //Memory model contains default graph. General model does not. System.out.println(memory.containsNamedModel(Quad.defaultGraphIRI.getURI())); //true System.out.println(general.containsNamedModel(Quad.defaultGraphIRI.getURI())); //false memory.addNamedModel("bar", ModelFactory.createDefaultModel()); general.addNamedModel("bar", ModelFactory.createDefaultModel()); //Memory model add == merge. General model add == replace. System.out.println(memory.getNamedModel("bar")); //merge System.out.println(general.getNamedModel("bar")); //replace }
Re: consistent blank id values from RDFConnection
You're right, that section does seem conclusive, at least insofar as SPARQL is concerned. From: ajs6f <aj...@apache.org> Sent: Sunday, December 17, 2017 10:19 AM To: dev@jena.apache.org Subject: Re: consistent blank id values from RDFConnection That's not how I understand: https://www.w3.org/TR/sparql11-query/#BlankNodesInResults "Blank node labels are scoped to a result set (see "SPARQL Query Results XML Format" and "SPARQL 1.1 Query Results JSON Format") or, for the CONSTRUCT query form, the result graph." Multiple calls to a single graph => multiple queries => multiple result sets (or result graphs) => multiple scopes. ajs6f > On Dec 17, 2017, at 11:15 AM, Adam Jacobs <jacobs_...@hotmail.com> wrote: > > My understanding is there's nothing wrong with maintaining labels among > multiple calls to a single graph. > The danger would be the risk of maintaining labels among calls to multiple > graphs. > At least, that's what I get out of this SO answer: > https://stackoverflow.com/questions/44477876/grouping-by-blank-nodes/44498034#44498034 > > > From: ajs6f <aj...@apache.org> > Sent: Sunday, December 17, 2017 10:11 AM > To: dev@jena.apache.org > Subject: Re: consistent blank id values from RDFConnection > >> On Dec 17, 2017, at 11:08 AM, Andy Seaborne <a...@apache.org> wrote: >> >>> Why would it be dangerous? > > As I wrote: > >>>> (in the sense in which you used the phrase "dubious in terms of spec >>>> compliance") > > It might confuse people into thinking that maintaining bnode labeling is a > normal part of using SPARQL, when it isn't-- it's something extra that Jena > provides. > > If there's no reason this is an undocumented feature, I'm going to document > it at: > > https://jena.apache.org/documentation/query/app_api.html > > ajs6f > >> On Dec 17, 2017, at 11:08 AM, Andy Seaborne <a...@apache.org> wrote: >> >> Why would it be dangerous? >> >> On 17/12/17 15:46, ajs6f wrote: >>> That is useful, and it's undocumented. Is that because it is dangerous (in >>> the sense in which you used the phrase "dubious in terms of spec >>> compliance") or just because we never have documented it? >>> ajs6f >>>> On Dec 17, 2017, at 10:43 AM, Andy Seaborne <a...@apache.org> wrote: >>>> >>>> ARQ.enableBlankNodeResultLabels() >>>> >>>> On 17/12/17 15:39, ajs6f wrote: >>>>> Where? I found nothing documented. >>>>> ajs6f >>>>>> On Dec 17, 2017, at 10:38 AM, Andy Seaborne <a...@apache.org> wrote: >>>>>> >>>>>> On 17/12/17 15:19, ajs6f wrote: >>>>>>> Claude-- I'm looking at RDFConnection, but it's an interface. I think >>>>>>> you mean around L220 of JSONInput itself, right? >>>>>>> It looks like SyntaxLabels has some LabelToNode factory methods that >>>>>>> might fit the bill, like createNodeToLabelAsGiven(), but JSONInput >>>>>>> doesn't offer any way to select which method to use. At L195 it uses >>>>>>> SyntaxLabels.createLabelToNode(). >>>>>>> We could thread such a mapping choice all the way through the call >>>>>>> stack, but that seems a bit difficult to me. Maybe we could introduce a >>>>>>> Context setting for this purpose? >>>>>> >>>>>> They already exist! >
Re: consistent blank id values from RDFConnection
My understanding is there's nothing wrong with maintaining labels among multiple calls to a single graph. The danger would be the risk of maintaining labels among calls to multiple graphs. At least, that's what I get out of this SO answer: https://stackoverflow.com/questions/44477876/grouping-by-blank-nodes/44498034#44498034 From: ajs6fSent: Sunday, December 17, 2017 10:11 AM To: dev@jena.apache.org Subject: Re: consistent blank id values from RDFConnection > On Dec 17, 2017, at 11:08 AM, Andy Seaborne wrote: > >> Why would it be dangerous? As I wrote: >>> (in the sense in which you used the phrase "dubious in terms of spec >>> compliance") It might confuse people into thinking that maintaining bnode labeling is a normal part of using SPARQL, when it isn't-- it's something extra that Jena provides. If there's no reason this is an undocumented feature, I'm going to document it at: https://jena.apache.org/documentation/query/app_api.html ajs6f > On Dec 17, 2017, at 11:08 AM, Andy Seaborne wrote: > > Why would it be dangerous? > > On 17/12/17 15:46, ajs6f wrote: >> That is useful, and it's undocumented. Is that because it is dangerous (in >> the sense in which you used the phrase "dubious in terms of spec >> compliance") or just because we never have documented it? >> ajs6f >>> On Dec 17, 2017, at 10:43 AM, Andy Seaborne wrote: >>> >>> ARQ.enableBlankNodeResultLabels() >>> >>> On 17/12/17 15:39, ajs6f wrote: Where? I found nothing documented. ajs6f > On Dec 17, 2017, at 10:38 AM, Andy Seaborne wrote: > > On 17/12/17 15:19, ajs6f wrote: >> Claude-- I'm looking at RDFConnection, but it's an interface. I think >> you mean around L220 of JSONInput itself, right? >> It looks like SyntaxLabels has some LabelToNode factory methods that >> might fit the bill, like createNodeToLabelAsGiven(), but JSONInput >> doesn't offer any way to select which method to use. At L195 it uses >> SyntaxLabels.createLabelToNode(). >> We could thread such a mapping choice all the way through the call >> stack, but that seems a bit difficult to me. Maybe we could introduce a >> Context setting for this purpose? > > They already exist!
[jira] [Commented] (JENA-1427) Add nextOrElse() method in ExtendedIterator
[ https://issues.apache.org/jira/browse/JENA-1427?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16263362#comment-16263362 ] Adam Jacobs commented on JENA-1427: --- Sounds great to me. Whether integrating with Java's {{Optional}} or implementing equivalent functionality, either way will work. > Add nextOrElse() method in ExtendedIterator > --- > > Key: JENA-1427 > URL: https://issues.apache.org/jira/browse/JENA-1427 > Project: Apache Jena > Issue Type: Improvement > Components: Core >Affects Versions: Jena 3.5.0 > Reporter: Adam Jacobs >Priority: Trivial > Labels: easytask > > Allow a functional approach for returning a default value or throwing a > custom exception from a Jena iterator. > The following method may be added to the ExtendedIterator interface. > {noformat} > /** > Answer the next object, if it exists, otherwise invoke the > _supplier_. > */ > public default T nextOrElse( Supplier supplier ) { > return hasNext() ? next() : supplier.get(); > } > {noformat} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Commented] (JENA-1427) Add nextOrElse() method in ExtendedIterator
[ https://issues.apache.org/jira/browse/JENA-1427?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16257388#comment-16257388 ] Adam Jacobs commented on JENA-1427: --- Utility methods don't enable the same fluent style of functional programming as what {{ExtendedIterator}} offers today... > Add nextOrElse() method in ExtendedIterator > --- > > Key: JENA-1427 > URL: https://issues.apache.org/jira/browse/JENA-1427 > Project: Apache Jena > Issue Type: Improvement > Components: Core >Affects Versions: Jena 3.5.0 > Reporter: Adam Jacobs >Priority: Trivial > Labels: easytask > > Allow a functional approach for returning a default value or throwing a > custom exception from a Jena iterator. > The following method may be added to the ExtendedIterator interface. > {noformat} > /** > Answer the next object, if it exists, otherwise invoke the > _supplier_. > */ > public default T nextOrElse( Supplier supplier ) { > return hasNext() ? next() : supplier.get(); > } > {noformat} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Commented] (JENA-1427) Add nextOrElse() method in ExtendedIterator
[ https://issues.apache.org/jira/browse/JENA-1427?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16257356#comment-16257356 ] Adam Jacobs commented on JENA-1427: --- One more thought, rather than adding more functional methods to {{ExtendedIterator}}, perhaps give it the ability to convert into a Java {{Stream}}. https://stackoverflow.com/questions/24511052/how-to-convert-an-iterator-to-a-stream {noformat} public default Stream toStream() { return StreamSupport.stream(Spliterators.spliteratorUnknownSize(this, Spliterator.ORDERED), false); } {noformat} Or give ExtendedIterator all of these methods! :) > Add nextOrElse() method in ExtendedIterator > --- > > Key: JENA-1427 > URL: https://issues.apache.org/jira/browse/JENA-1427 > Project: Apache Jena > Issue Type: Improvement > Components: Core >Affects Versions: Jena 3.5.0 > Reporter: Adam Jacobs >Priority: Trivial > Labels: easytask > > Allow a functional approach for returning a default value or throwing a > custom exception from a Jena iterator. > The following method may be added to the ExtendedIterator interface. > {noformat} > /** > Answer the next object, if it exists, otherwise invoke the > _supplier_. > */ > public default T nextOrElse( Supplier supplier ) { > return hasNext() ? next() : supplier.get(); > } > {noformat} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Commented] (JENA-1427) Add nextOrElse() method in ExtendedIterator
[ https://issues.apache.org/jira/browse/JENA-1427?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16257346#comment-16257346 ] Adam Jacobs commented on JENA-1427: --- {{Optional}} does add an extra object and an extra call in the functional chain. {noformat} RDFNode object = model.listObjectsOfProperty(subject, predicate).nextOptional().orElseThrow(() -> new IllegalStateException("No objects found for subject and predicate...")); {noformat} But it would still solve my use case. Perhaps this is a better method for ExtendedIterator? {noformat} public default Optional nextOptional() { return hasNext() ? Optional.of(next()) : Optional.empty(); } {noformat} I wouldn't mind having both methods! :) > Add nextOrElse() method in ExtendedIterator > --- > > Key: JENA-1427 > URL: https://issues.apache.org/jira/browse/JENA-1427 > Project: Apache Jena > Issue Type: Improvement > Components: Core >Affects Versions: Jena 3.5.0 >Reporter: Adam Jacobs >Priority: Trivial > Labels: easytask > > Allow a functional approach for returning a default value or throwing a > custom exception from a Jena iterator. > The following method may be added to the ExtendedIterator interface. > {noformat} > /** > Answer the next object, if it exists, otherwise invoke the > _supplier_. > */ > public default T nextOrElse( Supplier supplier ) { > return hasNext() ? next() : supplier.get(); > } > {noformat} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
Re: Generic RDFVisitor
I don't actually have a use case for the generics. I just saw that the interface was implemented in a pre-Java 5 style and wondered if it would help to modernize it, without breaking backwards compatibility of course. If the interface isn't used much, that probably answers my question. :) From: ajs6f <aj...@apache.org> Sent: Friday, November 17, 2017 11:03 AM To: dev@jena.apache.org Subject: Re: Generic RDFVisitor Perhaps you can say a little more about your use case here? I think we could probably work something out for this feature, but I am curious about why you are reaching for the visitor pattern? ajs6f > On Nov 17, 2017, at 11:27 AM, Adam Jacobs <jacobs_...@hotmail.com> wrote: > > Perhaps only a single generic parameter then, if each method should return > the same type. > Or a sub-interface in which all three parameters are the same, the way that > Java's `UnaryOperator` is related to `Function`. > > > > From: ajs6f <aj...@apache.org> > Sent: Friday, November 17, 2017 10:01 AM > To: dev@jena.apache.org > Subject: Re: Generic RDFVisitor > > Not sure how that would play against: > > Object org.apache.jena.rdf.model.impl.ResourceImpl.visitWith(RDFVisitor) > > OTOH, I'm not sure how much use the visitor pattern there has ever really > gotten... > > ajs6f > >> On Nov 17, 2017, at 10:55 AM, Adam Jacobs <jacobs_...@hotmail.com> wrote: >> >> I wonder if it would be useful to generify the `RDFVisitor` interface... >> >> public interface RDFVisitor<B,U,L> { >> >> B visitBlank( Resource r, AnonId id ); >> U visitURI( Resource r, String uri ); >> L visitLiteral( Literal l ); >> >> } >
[jira] [Commented] (JENA-1427) Add nextOrElse() method in ExtendedIterator
[ https://issues.apache.org/jira/browse/JENA-1427?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16257292#comment-16257292 ] Adam Jacobs commented on JENA-1427: --- The use case would be to consume only one element (or none) from the iterator. {noformat} RDFNode object = model.listObjectsOfProperty(subject, predicate).nextOrElse(() -> {throw new IllegalStateException("No objects found for subject and predicate...");}); {noformat} Often I have an {{ExtendedIterator}} as a result of one of the list...() methods on {{Model}} (listObjects, listResources, etc.). I expect one matching element to a query. If no element is present, I would like to throw a custom exception; otherwise, consume the element. More rarely, there is a sensible default value in case no elements are found. If multiple elements match the query, I do not need more than one. Occasionally, multiple elements could be considered an exception as well; but most often they do not matter. Writing this comment made me realize that a {{Model}} method which takes a SPO and returns an {{Optional}} might solve this case too; but there are so many variations of list methods on Model, to provide a version of each one that returns Optional. > Add nextOrElse() method in ExtendedIterator > --- > > Key: JENA-1427 > URL: https://issues.apache.org/jira/browse/JENA-1427 > Project: Apache Jena > Issue Type: Improvement > Components: Core >Affects Versions: Jena 3.5.0 >Reporter: Adam Jacobs >Priority: Trivial > Labels: easytask > > Allow a functional approach for returning a default value or throwing a > custom exception from a Jena iterator. > The following method may be added to the ExtendedIterator interface. > {noformat} > /** > Answer the next object, if it exists, otherwise invoke the > _supplier_. > */ > public default T nextOrElse( Supplier supplier ) { > return hasNext() ? next() : supplier.get(); > } > {noformat} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Updated] (JENA-1427) Add nextOrElse() method in ExtendedIterator
[ https://issues.apache.org/jira/browse/JENA-1427?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Adam Jacobs updated JENA-1427: -- Description: Allow a functional approach for returning a default value or throwing a custom exception from a Jena iterator. The following method may be added to the ExtendedIterator interface. {noformat} /** Answer the next object, if it exists, otherwise invoke the _supplier_. */ public default T nextOrElse( Supplier supplier ) { return hasNext() ? next() : supplier.get(); } {noformat} was: Allow a functional approach for returning a default value or throwing a custom exception from a Jena iterator. The following method may be added to the ExtendedIterator interface. {{/** Answer the next object, if it exists, otherwise invoke the _supplier_. */ public default T nextOrElse( Supplier supplier ) { return hasNext() ? next() : supplier.get(); } }} > Add nextOrElse() method in ExtendedIterator > --- > > Key: JENA-1427 > URL: https://issues.apache.org/jira/browse/JENA-1427 > Project: Apache Jena > Issue Type: Improvement > Components: Core >Affects Versions: Jena 3.5.0 > Reporter: Adam Jacobs >Priority: Trivial > Labels: easytask > > Allow a functional approach for returning a default value or throwing a > custom exception from a Jena iterator. > The following method may be added to the ExtendedIterator interface. > {noformat} > /** > Answer the next object, if it exists, otherwise invoke the > _supplier_. > */ > public default T nextOrElse( Supplier supplier ) { > return hasNext() ? next() : supplier.get(); > } > {noformat} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Created] (JENA-1427) Add nextOrElse() method in ExtendedIterator
Adam Jacobs created JENA-1427: - Summary: Add nextOrElse() method in ExtendedIterator Key: JENA-1427 URL: https://issues.apache.org/jira/browse/JENA-1427 Project: Apache Jena Issue Type: Improvement Components: Core Affects Versions: Jena 3.5.0 Reporter: Adam Jacobs Priority: Trivial Allow a functional approach for returning a default value or throwing a custom exception from a Jena iterator. The following method may be added to the ExtendedIterator interface. {{/** Answer the next object, if it exists, otherwise invoke the _supplier_. */ public default T nextOrElse( Supplier supplier ) { return hasNext() ? next() : supplier.get(); } }} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
Re: Generic RDFVisitor
Perhaps only a single generic parameter then, if each method should return the same type. Or a sub-interface in which all three parameters are the same, the way that Java's `UnaryOperator` is related to `Function`. From: ajs6f <aj...@apache.org> Sent: Friday, November 17, 2017 10:01 AM To: dev@jena.apache.org Subject: Re: Generic RDFVisitor Not sure how that would play against: Object org.apache.jena.rdf.model.impl.ResourceImpl.visitWith(RDFVisitor) OTOH, I'm not sure how much use the visitor pattern there has ever really gotten... ajs6f > On Nov 17, 2017, at 10:55 AM, Adam Jacobs <jacobs_...@hotmail.com> wrote: > > I wonder if it would be useful to generify the `RDFVisitor` interface... > > public interface RDFVisitor<B,U,L> { > >B visitBlank( Resource r, AnonId id ); >U visitURI( Resource r, String uri ); >L visitLiteral( Literal l ); > > }
Immutability
The subject of immutability was raised in JENA-1391 (https://issues.apache.org/jira/browse/JENA-1391). Specifically, the `getUnionModel` method in Jena 3.4 returns an immutable model view, and the implementation of the aforementioned story includes methods that will return an immutable dataset view. The question is whether these immutable views deserve their own interfaces. Currently, the views are returned using what I called "unexpected immutability" because they implement mutable interfaces. This introduces the potential for `UnsupportedOperationException`s. Unfortunately, that (degenerate) pattern is used in Java's `Collections` utility as well (https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html) but Scala is a clean example to draw inspiration from: by implementing immutable interfaces as parents to their mutable counterparts (rather than vice verse) we can satisfy the Liskov Substitution Principle. Obviously, implementing that solution is easier to do from scratch than in an existing code base; but I imagine it could be done in multiple phases, by introducing the new interfaces and using them in new methods (with easy conversion to mutability via union) while gradually retrofitting older methods. The question then, is whether such a change is worthwhile...
[jira] [Commented] (JENA-1391) Add Convenience Methods to Dataset
[ https://issues.apache.org/jira/browse/JENA-1391?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16241171#comment-16241171 ] Adam Jacobs commented on JENA-1391: --- One additional method from the {{Model}} interface that would be nice to have on {{Dataset}} would be {{isIsomorphicWith}}. Presumably it's just a matter of iterating over the graphs and comparing them. > Add Convenience Methods to Dataset > -- > > Key: JENA-1391 > URL: https://issues.apache.org/jira/browse/JENA-1391 > Project: Apache Jena > Issue Type: Improvement > Components: ARQ >Affects Versions: Jena 3.4.0 > Reporter: Adam Jacobs >Assignee: A. Soroka >Priority: Trivial > > The Dataset interface could provide several convenience methods similar to > the Model interface, allowing usability of RDF quads on par with RDF triples. > Specific examples include, > # add(Dataset) > # remove(Dataset) > # union(Dataset) > # intersection(Dataset) > # difference(Dataset) > # isEmpty() > Following is a possible implementation of these methods. > {code:java} > default Dataset add(Dataset d) { > this.getDefaultModel().add(d.getDefaultModel()); > d.listNames().forEachRemaining(name -> > this.getNamedModel(name).add(d.getNamedModel(name))); > return this; > } > default Dataset remove(Dataset d) { > this.getDefaultModel().remove(d.getDefaultModel()); > d.listNames().forEachRemaining(name -> > this.getNamedModel(name).remove(d.getNamedModel(name))); > return this; > } > default Dataset union(Dataset d) { > return DatasetFactory.create().add(this).add(d); > } > default Dataset difference(Dataset d) { > Dataset output = DatasetFactory.create(); > > output.setDefaultModel(this.getDefaultModel().difference(d.getDefaultModel())); > this.listNames().forEachRemaining(name -> { > Model difference = > this.getNamedModel(name).difference(d.getNamedModel(name)); > if (!difference.isEmpty()) output.addNamedModel(name, difference); > }); > return output; > } > default Dataset intersection(Dataset d) { > Dataset output = DatasetFactory.create(); > > output.setDefaultModel(this.getDefaultModel().intersection(d.getDefaultModel())); > Set names = this.names(); > names.retainAll(d.names()); > names.forEach(name -> { > Model intersection = > this.getNamedModel(name).intersection(d.getNamedModel(name)); > if (!intersection.isEmpty()) output.addNamedModel(name, > intersection); > }); > return output; > } > default Set names() { > Set names = new HashSet<>(); > this.listNames().forEachRemaining(names::add); > return names; > } > default boolean isEmpty() { > return this.asDatasetGraph().isEmpty(); > } > {code} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Comment Edited] (JENA-1391) Add Convenience Methods to Dataset
[ https://issues.apache.org/jira/browse/JENA-1391?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16239546#comment-16239546 ] Adam Jacobs edited comment on JENA-1391 at 11/5/17 1:55 PM: The integration with Java's {{Collector}} interface looks very nice. That should help future-proof the design. Given an immutable view of the underlying graph, having the {{DatasetLib}} return a new {{ImmutableDataset}} interface would avoid the potential for {{UnsupportedOperationException}} s. Since the implementation of the {{getUnionModel}} method in Jena 3.4, I've been bitten a couple of times by unexpected immutability. In retrospect, I wish there was an {{ImmutableModel}} interface for that method to return as well. was (Author: jaco0646): The integration with Java's {{Collector}} interface looks very nice. That should help future-proof the design. Given an immutable view of the underlying graph, having the {{DatasetLib}} return a new {{ImmutableDataset}} interface would avoid the potential for {{UnsupportedOperationException}}s. (Since the implementation of the {{getUnionModel}} method in Jena 3.4, I've been bitten a couple of times by unexpected immutability. In retrospect, I wish there was an {{ImmutableModel}} interface for that method to return as well.) > Add Convenience Methods to Dataset > -- > > Key: JENA-1391 > URL: https://issues.apache.org/jira/browse/JENA-1391 > Project: Apache Jena > Issue Type: Improvement > Components: ARQ >Affects Versions: Jena 3.4.0 > Reporter: Adam Jacobs >Assignee: A. Soroka >Priority: Trivial > > The Dataset interface could provide several convenience methods similar to > the Model interface, allowing usability of RDF quads on par with RDF triples. > Specific examples include, > # add(Dataset) > # remove(Dataset) > # union(Dataset) > # intersection(Dataset) > # difference(Dataset) > # isEmpty() > Following is a possible implementation of these methods. > {code:java} > default Dataset add(Dataset d) { > this.getDefaultModel().add(d.getDefaultModel()); > d.listNames().forEachRemaining(name -> > this.getNamedModel(name).add(d.getNamedModel(name))); > return this; > } > default Dataset remove(Dataset d) { > this.getDefaultModel().remove(d.getDefaultModel()); > d.listNames().forEachRemaining(name -> > this.getNamedModel(name).remove(d.getNamedModel(name))); > return this; > } > default Dataset union(Dataset d) { > return DatasetFactory.create().add(this).add(d); > } > default Dataset difference(Dataset d) { > Dataset output = DatasetFactory.create(); > > output.setDefaultModel(this.getDefaultModel().difference(d.getDefaultModel())); > this.listNames().forEachRemaining(name -> { > Model difference = > this.getNamedModel(name).difference(d.getNamedModel(name)); > if (!difference.isEmpty()) output.addNamedModel(name, difference); > }); > return output; > } > default Dataset intersection(Dataset d) { > Dataset output = DatasetFactory.create(); > > output.setDefaultModel(this.getDefaultModel().intersection(d.getDefaultModel())); > Set names = this.names(); > names.retainAll(d.names()); > names.forEach(name -> { > Model intersection = > this.getNamedModel(name).intersection(d.getNamedModel(name)); > if (!intersection.isEmpty()) output.addNamedModel(name, > intersection); > }); > return output; > } > default Set names() { > Set names = new HashSet<>(); > this.listNames().forEachRemaining(names::add); > return names; > } > default boolean isEmpty() { > return this.asDatasetGraph().isEmpty(); > } > {code} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Commented] (JENA-1391) Add Convenience Methods to Dataset
[ https://issues.apache.org/jira/browse/JENA-1391?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16239546#comment-16239546 ] Adam Jacobs commented on JENA-1391: --- The integration with Java's {{Collector}} interface looks very nice. That should help future-proof the design. Given an immutable view of the underlying graph, having the {{DatasetLib}} return a new {{ImmutableDataset}} interface would avoid the potential for {{UnsupportedOperationException}}s. (Since the implementation of the {{getUnionModel}} method in Jena 3.4, I've been bitten a couple of times by unexpected immutability. In retrospect, I wish there was an {{ImmutableModel}} interface for that method to return as well.) > Add Convenience Methods to Dataset > -- > > Key: JENA-1391 > URL: https://issues.apache.org/jira/browse/JENA-1391 > Project: Apache Jena > Issue Type: Improvement > Components: ARQ >Affects Versions: Jena 3.4.0 > Reporter: Adam Jacobs >Assignee: A. Soroka >Priority: Trivial > > The Dataset interface could provide several convenience methods similar to > the Model interface, allowing usability of RDF quads on par with RDF triples. > Specific examples include, > # add(Dataset) > # remove(Dataset) > # union(Dataset) > # intersection(Dataset) > # difference(Dataset) > # isEmpty() > Following is a possible implementation of these methods. > {code:java} > default Dataset add(Dataset d) { > this.getDefaultModel().add(d.getDefaultModel()); > d.listNames().forEachRemaining(name -> > this.getNamedModel(name).add(d.getNamedModel(name))); > return this; > } > default Dataset remove(Dataset d) { > this.getDefaultModel().remove(d.getDefaultModel()); > d.listNames().forEachRemaining(name -> > this.getNamedModel(name).remove(d.getNamedModel(name))); > return this; > } > default Dataset union(Dataset d) { > return DatasetFactory.create().add(this).add(d); > } > default Dataset difference(Dataset d) { > Dataset output = DatasetFactory.create(); > > output.setDefaultModel(this.getDefaultModel().difference(d.getDefaultModel())); > this.listNames().forEachRemaining(name -> { > Model difference = > this.getNamedModel(name).difference(d.getNamedModel(name)); > if (!difference.isEmpty()) output.addNamedModel(name, difference); > }); > return output; > } > default Dataset intersection(Dataset d) { > Dataset output = DatasetFactory.create(); > > output.setDefaultModel(this.getDefaultModel().intersection(d.getDefaultModel())); > Set names = this.names(); > names.retainAll(d.names()); > names.forEach(name -> { > Model intersection = > this.getNamedModel(name).intersection(d.getNamedModel(name)); > if (!intersection.isEmpty()) output.addNamedModel(name, > intersection); > }); > return output; > } > default Set names() { > Set names = new HashSet<>(); > this.listNames().forEachRemaining(names::add); > return names; > } > default boolean isEmpty() { > return this.asDatasetGraph().isEmpty(); > } > {code} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Updated] (JENA-1391) Add Convenience Methods to Dataset
[ https://issues.apache.org/jira/browse/JENA-1391?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Adam Jacobs updated JENA-1391: -- Description: The Dataset interface could provide several convenience methods similar to the Model interface, allowing usability of RDF quads on par with RDF triples. Specific examples include, # add(Dataset) # remove(Dataset) # union(Dataset) # intersection(Dataset) # difference(Dataset) # isEmpty() Following is a possible implementation of these methods. {code:java} default Dataset add(Dataset d) { this.getDefaultModel().add(d.getDefaultModel()); d.listNames().forEachRemaining(name -> this.getNamedModel(name).add(d.getNamedModel(name))); return this; } default Dataset remove(Dataset d) { this.getDefaultModel().remove(d.getDefaultModel()); d.listNames().forEachRemaining(name -> this.getNamedModel(name).remove(d.getNamedModel(name))); return this; } default Dataset union(Dataset d) { return DatasetFactory.create().add(this).add(d); } default Dataset difference(Dataset d) { Dataset output = DatasetFactory.create(); output.setDefaultModel(this.getDefaultModel().difference(d.getDefaultModel())); this.listNames().forEachRemaining(name -> { Model difference = this.getNamedModel(name).difference(d.getNamedModel(name)); if (!difference.isEmpty()) output.addNamedModel(name, difference); }); return output; } default Dataset intersection(Dataset d) { Dataset output = DatasetFactory.create(); output.setDefaultModel(this.getDefaultModel().intersection(d.getDefaultModel())); Set names = this.names(); names.retainAll(d.names()); names.forEach(name -> { Model intersection = this.getNamedModel(name).intersection(d.getNamedModel(name)); if (!intersection.isEmpty()) output.addNamedModel(name, intersection); }); return output; } default Set names() { Set names = new HashSet<>(); this.listNames().forEachRemaining(names::add); return names; } default boolean isEmpty() { return this.asDatasetGraph().isEmpty(); } {code} was: The Dataset interface could provide several convenience methods similar to the Model interface, allowing usability of RDF quads on par with RDF triples. Specific examples include, # add(Dataset) # remove(Dataset) # union(Dataset) # intersection(Dataset) # difference(Dataset) # isEmpty() Following is a possible implementation of these methods. {code:java} default Dataset add(Dataset d) { this.getDefaultModel().add(d.getDefaultModel()); d.listNames().forEachRemaining(name -> this.getNamedModel(name).add(d.getNamedModel(name))); return this; } default Dataset remove(Dataset d) { this.getDefaultModel().remove(d.getDefaultModel()); d.listNames().forEachRemaining(name -> this.getNamedModel(name).remove(d.getNamedModel(name))); return this; } default Dataset union(Dataset d) { return DatasetFactory.create().add(this).add(d); } default Dataset difference(Dataset d) { Dataset output = DatasetFactory.create(); output.setDefaultModel(this.getDefaultModel().difference(d.getDefaultModel())); this.listNames().forEachRemaining(name -> { Model difference = this.getNamedModel(name).difference(d.getNamedModel(name)); if (!difference.isEmpty()) output.addNamedModel(name, difference); }); return output; } default Dataset intersection(Dataset d) { Dataset output = DatasetFactory.create(); output.setDefaultModel(this.getDefaultModel().intersection(d.getDefaultModel())); Set names = this.names(); names.retainAll(d.names()); names.forEach(name -> { Model intersection = this.getNamedModel(name).intersection(d.getNamedModel(name)); if (!intersection.isEmpty()) output.addNamedModel(name, intersection); }); return output; } default Set names() { Set names = new HashSet<>(); this.listNames().forEachRemaining(names::add); return names; } default boolean isEmpty() { return !listNames().hasNext() && getDefaultModel().isEmpty(); } {code} > Add Convenience Methods to Dataset > -- > > Key: JENA-1391 > URL: https://issues.apache.org/jira/browse/JENA-1391 > Project: Apache Jena > Issue Type: Improvement > Components: ARQ >Affects Versions: Jena 3.4.0 >Reporter: Adam Jacobs >Priority: Trivial > > The Dataset interface could provide several con
[jira] [Commented] (JENA-1391) Add Convenience Methods to Dataset
[ https://issues.apache.org/jira/browse/JENA-1391?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel=16155374#comment-16155374 ] Adam Jacobs commented on JENA-1391: --- Consistency between the `Dataset` and `Model` interfaces seems desirable to me; also, in my experience, single-argument methods play nicer with lambdas and streams in Java. I'm not sure about storages or transactions. Are these concerns different for Datasets vs. Models? Definitely could implement these in the SPI layer rather than API. I see the `isEmpty()` method is already there. > Add Convenience Methods to Dataset > -- > > Key: JENA-1391 > URL: https://issues.apache.org/jira/browse/JENA-1391 > Project: Apache Jena > Issue Type: Improvement > Components: ARQ >Affects Versions: Jena 3.4.0 > Reporter: Adam Jacobs >Priority: Trivial > > The Dataset interface could provide several convenience methods similar to > the Model interface, allowing usability of RDF quads on par with RDF triples. > Specific examples include, > # add(Dataset) > # remove(Dataset) > # union(Dataset) > # intersection(Dataset) > # difference(Dataset) > # isEmpty() > Following is a possible implementation of these methods. > {code:java} > default Dataset add(Dataset d) { > this.getDefaultModel().add(d.getDefaultModel()); > d.listNames().forEachRemaining(name -> > this.getNamedModel(name).add(d.getNamedModel(name))); > return this; > } > default Dataset remove(Dataset d) { > this.getDefaultModel().remove(d.getDefaultModel()); > d.listNames().forEachRemaining(name -> > this.getNamedModel(name).remove(d.getNamedModel(name))); > return this; > } > default Dataset union(Dataset d) { > return DatasetFactory.create().add(this).add(d); > } > default Dataset difference(Dataset d) { > Dataset output = DatasetFactory.create(); > > output.setDefaultModel(this.getDefaultModel().difference(d.getDefaultModel())); > this.listNames().forEachRemaining(name -> { > Model difference = > this.getNamedModel(name).difference(d.getNamedModel(name)); > if (!difference.isEmpty()) output.addNamedModel(name, difference); > }); > return output; > } > default Dataset intersection(Dataset d) { > Dataset output = DatasetFactory.create(); > > output.setDefaultModel(this.getDefaultModel().intersection(d.getDefaultModel())); > Set names = this.names(); > names.retainAll(d.names()); > names.forEach(name -> { > Model intersection = > this.getNamedModel(name).intersection(d.getNamedModel(name)); > if (!intersection.isEmpty()) output.addNamedModel(name, > intersection); > }); > return output; > } > default Set names() { > Set names = new HashSet<>(); > this.listNames().forEachRemaining(names::add); > return names; > } > default boolean isEmpty() { > return !listNames().hasNext() && getDefaultModel().isEmpty(); > } > {code} -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Created] (JENA-1390) Add toModel() method in StmtIterator
Adam Jacobs created JENA-1390: - Summary: Add toModel() method in StmtIterator Key: JENA-1390 URL: https://issues.apache.org/jira/browse/JENA-1390 Project: Apache Jena Issue Type: Improvement Components: Core Affects Versions: Jena 3.4.0 Reporter: Adam Jacobs Priority: Trivial Add direct conversion of org.apache.jena.rdf.model.StmtIterator to Model. This would align with the toList() and toSet() functionality of ExtendedIterator. The following method may be added to the StmtIterator interface. /** Answer a Model of the [remaining] Statements of this iterator, consuming this iterator. */ public default Model toModel() { Model m = ModelFactory.createDefaultModel(); this.forEachRemaining(m::add); return m; } -- This message was sent by Atlassian JIRA (v6.4.14#64029)
[jira] [Created] (JENA-1389) Return `this` rather than `void` from Dataset
Adam Jacobs created JENA-1389: - Summary: Return `this` rather than `void` from Dataset Key: JENA-1389 URL: https://issues.apache.org/jira/browse/JENA-1389 Project: Apache Jena Issue Type: Improvement Components: ARQ Affects Versions: Jena 3.4.0 Reporter: Adam Jacobs Priority: Trivial Allow method chaining from the org.apache.jena.query.Dataset interface by returning `this` rather than `void` from the following methods. # setDefaultModel # addNamedModel # removeNamedModel # replaceNamedModel Allowing method chaining would align with the behavior of the add and remove methods in org.apache.jena.rdf.model.Model. -- This message was sent by Atlassian JIRA (v6.4.14#64029)