/** * Try to load a Trellis resource. * * @implSpec This method will load a {@link Resource}, initializing the object with all resource metadata * used with {@link #getModified}, {@link #getInteractionModel} and other data fetched by the accessors. * The resource content is fetched on demand via the {@link #stream} method. * @param rdfConnection the triplestore connector * @param identifier the identifier * @return a new completion stage with a {@link Resource}, if one exists */ public static CompletableFuture<Resource> findResource(final RDFConnection rdfConnection, final IRI identifier) { return supplyAsync(() -> { final TriplestoreResource res = new TriplestoreResource(rdfConnection, identifier); res.fetchData(); if (!res.exists()) { return MISSING_RESOURCE; } else if (res.isDeleted()) { return DELETED_RESOURCE; } return res; }); }
@Override public Optional<IRI> getContainer() { return asIRI(DC.isPartOf); }
@Override public Instant getModified() { return asLiteral(DC.modified).map(Instant::parse).orElse(null); }
private Stream<Quad> fetchMembershipQuads() { return concat(fetchIndirectMemberQuads(), concat(fetchDirectMemberQuads(), fetchDirectMemberQuadsInverse())); }
@Test public void testEmptyResource() { final TriplestoreResource res = new TriplestoreResource(connect(create()), identifier); res.fetchData(); assertFalse(res.exists(), "Unexpected resource!"); }
@Test public void testDirectContainer() { final JenaDataset dataset = buildLdpDataset(LDP.DirectContainer); dataset.add(Trellis.PreferServerManaged, identifier, DC.isPartOf, root); dataset.add(Trellis.PreferServerManaged, identifier, LDP.member, member); dataset.add(Trellis.PreferServerManaged, identifier, LDP.membershipResource, member); dataset.add(Trellis.PreferServerManaged, identifier, LDP.hasMemberRelation, DC.subject); dataset.add(Trellis.PreferServerManaged, identifier, LDP.insertedContentRelation, LDP.MemberSubject); dataset.add(Trellis.PreferServerManaged, identifier, DC.modified, rdf.createLiteral(time, XSD.dateTime)); dataset.add(Trellis.PreferServerManaged, member, DC.isPartOf, root); getChildIRIs().forEach(c -> dataset.add(Trellis.PreferServerManaged, c, DC.isPartOf, identifier)); final RDFConnection rdfConnection = connect(wrap(dataset.asJenaDatasetGraph())); final TriplestoreResource res = new TriplestoreResource(rdfConnection, identifier); res.fetchData(); assertTrue(res.exists(), "Missing resource!"); assertAll("Check resource", checkResource(res, identifier, LDP.DirectContainer, false, false, true)); assertAll("Check LDP properties", checkLdpProperties(res, member, DC.subject, null, LDP.MemberSubject)); assertAll("Check RDF stream", checkRdfStream(res, 2L, 0L, 0L, 0L, 4L)); final TriplestoreResource memberRes = new TriplestoreResource(rdfConnection, member); memberRes.fetchData(); assertTrue(memberRes.exists(), "Missing resource!"); assertAll("Check resource", checkResource(memberRes, member, LDP.RDFSource, false, false, true)); assertAll("Check LDP properties", checkLdpProperties(memberRes, null, null, null, null)); assertAll("Check RDF stream", checkRdfStream(memberRes, 1L, 0L, 0L, 4L, 0L)); assertEquals(4L, memberRes.stream(singleton(LDP.PreferMembership)).map(Triple::getPredicate) .filter(isEqual(DC.subject)).count(), "Incorrect triple count!"); }
@Test public void testBinaryResource() { final String mimeType = "image/jpeg"; final IRI binaryIdentifier = rdf.createIRI("file:///binary"); final JenaDataset dataset = buildLdpDataset(LDP.NonRDFSource); dataset.add(Trellis.PreferServerManaged, identifier, DC.hasPart, binaryIdentifier); dataset.add(Trellis.PreferServerManaged, binaryIdentifier, DC.format, rdf.createLiteral(mimeType)); auditService.creation(identifier, mockSession).forEach(q -> dataset.add(auditId, q.getSubject(), q.getPredicate(), q.getObject())); final TriplestoreResource res = new TriplestoreResource(connect(wrap(dataset.asJenaDatasetGraph())), identifier); res.fetchData(); assertTrue(res.exists(), "Missing resource!"); res.getBinaryMetadata().ifPresent(b -> { assertEquals(binaryIdentifier, b.getIdentifier(), "Incorrect binary identifier!"); assertEquals(of(mimeType), b.getMimeType(), "Incorrect binary mime type!"); }); assertAll("Check resource", checkResource(res, identifier, LDP.NonRDFSource, true, false, false)); assertAll("Check LDP properties", checkLdpProperties(res, null, null, null, null)); assertAll("Check RDF stream", checkRdfStream(res, 2L, 0L, 5L, 0L, 0L)); }
/** * This code is equivalent to the SPARQL query below. * * <p><pre><code> * SELECT ?subject ?predicate ?object * WHERE { GRAPH IDENTIFIER?ext=audit { ?subject ?predicate ?object } } * </code></pre> */ private Stream<Quad> fetchAuditQuads() { return fetchAllFromGraph(identifier.getIRIString() + "?ext=audit", Trellis.PreferAudit); }
@Override public boolean hasAcl() { return fetchAclQuads().findAny().isPresent(); }
@Test public void testPartialResource() { final JenaDataset dataset = rdf.createDataset(); dataset.add(Trellis.PreferServerManaged, identifier, DC.modified, rdf.createLiteral(time, XSD.dateTime)); final TriplestoreResource res = new TriplestoreResource(connect(wrap(dataset.asJenaDatasetGraph())), identifier); res.fetchData(); assertFalse(res.exists(), "Unexpected resource!"); }
final TriplestoreResource res = new TriplestoreResource(rdfConnection, identifier); res.fetchData(); assertTrue(res.exists(), "Missing resource!"); assertAll("Check resource", checkResource(res, identifier, LDP.IndirectContainer, false, false, true)); assertAll("Check LDP properties", checkLdpProperties(res, member, DC.relation, null, DC.subject)); assertAll("Check RDF stream", checkRdfStream(res, 3L, 0L, 0L, 0L, 4L)); final TriplestoreResource res2 = new TriplestoreResource(rdfConnection, member); res2.fetchData(); assertTrue(res2.exists(), "Missing resource (2)!"); assertAll("Check resource", checkResource(res2, member, LDP.RDFSource, false, false, true)); assertAll("Check LDP properties", checkLdpProperties(res2, null, null, null, null)); assertAll("Check RDF stream", checkRdfStream(res2, 2L, 0L, 0L, 4L, 0L)); assertEquals(4L, res2.stream(singleton(LDP.PreferMembership)).map(Triple::getPredicate) .filter(isEqual(DC.relation)).count(), "Incorrect triple count!");
private Stream<Quad> fetchMembershipQuads() { return concat(fetchIndirectMemberQuads(), concat(fetchDirectMemberQuads(), fetchDirectMemberQuadsInverse())); }
/** * This code is equivalent to the SPARQL query below. * * <p><pre><code> * SELECT ?subject ?predicate ?object * WHERE { GRAPH IDENTIFIER?ext=audit { ?subject ?predicate ?object } } * </code></pre> */ private Stream<Quad> fetchAuditQuads() { return fetchAllFromGraph(identifier.getIRIString() + "?ext=audit", Trellis.PreferAudit); }
@Override public boolean hasAcl() { return fetchAclQuads().findAny().isPresent(); }
@Test public void testMinimalResource() { final JenaDataset dataset = buildLdpDataset(LDP.RDFSource); final TriplestoreResource res = new TriplestoreResource(connect(wrap(dataset.asJenaDatasetGraph())), identifier); res.fetchData(); assertTrue(res.exists(), "Missing resource!"); assertAll("Check resource", checkResource(res, identifier, LDP.RDFSource, false, false, false)); assertAll("Check LDP properties", checkLdpProperties(res, null, null, null, null)); assertAll("Check RDF stream", checkRdfStream(res, 2L, 0L, 0L, 0L, 0L)); }
/** * Try to load a Trellis resource. * * @implSpec This method will load a {@link Resource}, initializing the object with all resource metadata * used with {@link #getModified}, {@link #getInteractionModel} and other data fetched by the accessors. * The resource content is fetched on demand via the {@link #stream} method. * @param rdfConnection the triplestore connector * @param identifier the identifier * @return a new completion stage with a {@link Resource}, if one exists */ public static CompletableFuture<Resource> findResource(final RDFConnection rdfConnection, final IRI identifier) { return supplyAsync(() -> { final TriplestoreResource res = new TriplestoreResource(rdfConnection, identifier); res.fetchData(); if (!res.exists()) { return MISSING_RESOURCE; } else if (res.isDeleted()) { return DELETED_RESOURCE; } return res; }); }
@Override public Optional<IRI> getInsertedContentRelation() { return asIRI(LDP.insertedContentRelation); }
/** * This code is equivalent to the SPARQL query below. * * <p><pre><code> * SELECT ?subject ?predicate ?object * WHERE { GRAPH IDENTIFIER?ext=acl { ?subject ?predicate ?object } } * </code></pre> */ private Stream<Quad> fetchAclQuads() { return fetchAllFromGraph(identifier.getIRIString() + "?ext=acl", Trellis.PreferAccessControl); }