/** * Check a graph against an LDP interaction model. * * @param interactionModel the interaction model * @param graph the graph * @return any constraint violations on the graph */ default Stream<ConstraintViolation> constrainedBy(IRI interactionModel, Graph graph) { return constrainedBy(interactionModel, graph, TrellisUtils.TRELLIS_DATA_PREFIX); } }
/** * Check a graph against an LDP interaction model. * * @param interactionModel the interaction model * @param graph the graph * @return any constraint violations on the graph */ default Stream<ConstraintViolation> constrainedBy(IRI interactionModel, Graph graph) { return constrainedBy(interactionModel, graph, TrellisUtils.TRELLIS_DATA_PREFIX); } }
private static Function<ConstraintService, Stream<ConstraintViolation>> handleConstraintViolations( final TrellisDataset dataset, final IRI graphName, final IRI interactionModel) { final IRI model = PreferAccessControl.equals(graphName) ? LDP.RDFSource : interactionModel; return service -> dataset.getGraph(graphName).map(Stream::of).orElseGet(Stream::empty) .flatMap(g -> service.constrainedBy(model, g)); }
/** * Check the constraints of a graph. * @param graph the graph * @param type the LDP interaction model * @param syntax the output syntax */ protected void checkConstraint(final Graph graph, final IRI type, final RDFSyntax syntax) { ofNullable(graph).map(g -> constraintServices.stream().parallel().flatMap(svc -> svc.constrainedBy(type, g)).collect(toList())) .filter(violations -> !violations.isEmpty()) .map(violations -> { final ResponseBuilder err = status(CONFLICT); violations.forEach(v -> err.link(v.getConstraint().getIRIString(), LDP.constrainedBy.getIRIString())); final StreamingOutput stream = new StreamingOutput() { @Override public void write(final OutputStream out) throws IOException { getServices().getIOService().write(violations.stream().flatMap(v2 -> v2.getTriples().stream()), out, syntax); } }; return err.entity(stream); }).ifPresent(err -> { throw new ClientErrorException(err.build()); }); }
@Test public void testConstrainedBy() { final ConstraintService svc = mock(ConstraintService.class); doCallRealMethod().when(svc).constrainedBy(eq(LDP.RDFSource), any(Graph.class)); when(svc.constrainedBy(any(IRI.class), any(Graph.class), eq(TrellisUtils.TRELLIS_DATA_PREFIX))) .thenAnswer(inv -> Stream.empty()); assertEquals(0L, svc.constrainedBy(LDP.RDFSource, rdf.createGraph()).count(), "Unexpected constraint found"); } }
@Test public void testCardinality() { assertEquals(0L, models.stream() .filter(type -> !svc.constrainedBy(type, asGraph("/invalidCardinality.ttl", domain + "foo"), domain) .findFirst().isPresent()) .count(), "unexpected constraint violation found!"); models.stream().forEach(type -> { final String subject = domain + "foo"; final Optional<ConstraintViolation> res = svc.constrainedBy(type, asGraph("/invalidCardinality.ttl", subject), domain).findFirst(); assertTrue(res.isPresent(), "no constraint violation found for " + type); res.ifPresent(violation -> assertEquals(Trellis.InvalidCardinality, violation.getConstraint(), "no InvalidCardinality violation")); }); }
@Test public void testLdpType() { assertFalse(models.stream().map(ldpType -> svc.constrainedBy(ldpType, asGraph("/withLdpType.ttl", domain + "foo"), domain).anyMatch(v -> Trellis.InvalidType.equals(v.getConstraint()))) .reduce(false, (acc, x) -> acc || x), "Unexpected constraint violation!"); }
@Test public void testTooManyMembershipTriples() { final Optional<ConstraintViolation> res = svc.constrainedBy(LDP.IndirectContainer, asGraph("/tooManyMembershipTriples.ttl", domain + "foo"), domain).findFirst(); assertTrue(res.isPresent(), "no constraint violation found!"); res.ifPresent(violation -> assertEquals(Trellis.InvalidCardinality, violation.getConstraint(), "no InvalidCardinality violation!")); }
@Test public void testInvalidType2() { final Optional<ConstraintViolation> res = svc.constrainedBy(LDP.RDFSource, asGraph("/invalidType.ttl", domain + "foo"), domain) .filter(v -> v.getConstraint().equals(Trellis.InvalidRange)).findFirst(); assertTrue(res.isPresent(), "no constraint violation found!"); res.ifPresent(violation -> assertEquals(Trellis.InvalidRange, violation.getConstraint(), "no InvalidRange violation!")); }
@Test public void testInvalidInsertedContentRelation() { final List<IRI> found = models.stream() .filter(type -> svc.constrainedBy(type, asGraph("/hasInsertedContent.ttl", domain + "foo"), domain) .findFirst().isPresent()) .collect(toList()); assertTrue(found.contains(LDP.Container), "ldp:Container not present!"); assertFalse(found.contains(LDP.DirectContainer), "ldp:DirectContainer not expected!"); assertFalse(found.contains(LDP.IndirectContainer), "ldp:IndirectContainer not expected!"); models.stream().forEach(type -> { final String subject = domain + "foo"; final Optional<ConstraintViolation> res = svc.constrainedBy(type, asGraph("/hasInsertedContent.ttl", subject), domain).findFirst(); if (type.equals(LDP.IndirectContainer) || type.equals(LDP.DirectContainer)) { assertFalse(res.isPresent(), "constraint violation not expected for " + type); } else { assertTrue(res.isPresent(), "constraint violation not found for " + type); res.ifPresent(violation -> { assertEquals(Trellis.InvalidProperty, violation.getConstraint(), "no InvalidProperty violation!"); assertTrue(violation.getTriples().contains( rdf.createTriple(rdf.createIRI(subject), LDP.hasMemberRelation, DC.isPartOf)), "Triple missing from violation!"); }); } }); }
@Test public void testMembershipTriples2() { final Optional<ConstraintViolation> res = svc.constrainedBy(LDP.DirectContainer, asGraph("/invalidMembershipTriple2.ttl", domain + "foo"), domain).findFirst(); assertTrue(res.isPresent(), "no constraint violation found!"); res.ifPresent(violation -> { assertEquals(Trellis.InvalidRange, violation.getConstraint(), "no InvalidRange violation found!"); assertTrue(violation.getTriples().contains(rdf.createTriple(rdf.createIRI(domain + "foo"), LDP.isMemberOfRelation, LDP.contains)), "Expected triple not found in violation!"); }); }
@Test public void testInvalidLdpProps() { final List<IRI> found = models.stream() .filter(type -> svc.constrainedBy(type, asGraph("/basicContainer.ttl", domain + "foo"), domain) .findFirst().isPresent()) .collect(toList()); assertTrue(found.contains(LDP.Container), "ldp:Container not present!"); assertFalse(found.contains(LDP.DirectContainer), "ldp:DirectContainer not expected!"); assertFalse(found.contains(LDP.IndirectContainer), "ldp:IndirectContainer not expected!"); models.stream().forEach(type -> { final String subject = domain + "foo"; final Optional<ConstraintViolation> res = svc.constrainedBy(type, asGraph("/basicContainer.ttl", subject), domain).findFirst(); if (type.equals(LDP.DirectContainer) || type.equals(LDP.IndirectContainer)) { assertFalse(res.isPresent(), "constraint violation not expected for " + type); } else { assertTrue(res.isPresent(), "constraint violation not found for " + type); res.ifPresent(violation -> { assertEquals(Trellis.InvalidProperty, violation.getConstraint(), "no InvalidProperty violation!"); assertTrue(violation.getTriples().contains( rdf.createTriple(rdf.createIRI(subject), LDP.hasMemberRelation, DC.isPartOf)), "Triple missing from violation!"); }); } }); }
@Test public void testInvalidAccessControlProperty() { assertTrue(models.stream() .map(type -> svc.constrainedBy(type, asGraph("/hasAccessControlTriples.ttl", domain + "foo"), domain) .anyMatch(v -> v.getConstraint().equals(Trellis.InvalidProperty))) .reduce(true, (acc, x) -> acc && x), "InvalidProperty constraint not found!"); models.stream().forEach(type -> { final String subject = domain + "foo"; final Optional<ConstraintViolation> res = svc.constrainedBy(type, asGraph("/hasAccessControlTriples.ttl", subject), domain) .filter(v -> v.getConstraint().equals(Trellis.InvalidProperty)).findFirst(); assertTrue(res.isPresent(), "Constraint violation not found!"); res.ifPresent(violation -> { assertEquals(Trellis.InvalidProperty, violation.getConstraint(), "no InvalidProperty violation!"); assertTrue(violation.getTriples().contains( rdf.createTriple(rdf.createIRI(subject), ACL.accessControl, rdf.createIRI(domain + "bar"))), "Triple missing from violation!"); }); }); }
@Test public void testInvalidDomain() { assertEquals(0L, models.stream() .filter(type -> !svc.constrainedBy(type, asGraph("/invalidDomain.ttl", domain + "foo"), domain) .findAny().isPresent()) .count(), "Unexpected InvalidDomain violation!"); models.stream().forEach(type -> { final String subject = domain + "foo"; final List<ConstraintViolation> res = svc.constrainedBy(type, asGraph("/invalidDomain.ttl", subject), domain).collect(toList()); if (type.equals(LDP.DirectContainer) || type.equals(LDP.IndirectContainer)) { final Optional<ConstraintViolation> violation = res.stream() .filter(v -> v.getConstraint().equals(Trellis.InvalidRange)).findFirst(); assertTrue(violation.isPresent(), "no constraint violation for " + type); assertEquals(Trellis.InvalidRange, violation.get().getConstraint(), "no InvalidRange violation!"); assertTrue(violation.get().getTriples().contains(rdf.createTriple(rdf.createIRI(subject), LDP.membershipResource, DC.subject)), "Triple missing from violation!"); } else { final Optional<ConstraintViolation> violation = res.stream() .filter(v -> v.getConstraint().equals(Trellis.InvalidProperty)).findFirst(); assertTrue(violation.isPresent(), "no constraint violation for " + type); assertEquals(Trellis.InvalidProperty, violation.get().getConstraint(), "no InvalidProperty violation!"); assertTrue(violation.get().getTriples().contains(rdf.createTriple(rdf.createIRI(subject), LDP.hasMemberRelation, DC.creator)), "Triple missing from violation!"); } }); }
@Test public void testInvalidContainsProperty() { assertTrue(models.stream() .map(type -> svc.constrainedBy(type, asGraph("/hasLdpContainsTriples.ttl", domain + "foo"), domain) .anyMatch(v -> v.getConstraint().equals(Trellis.InvalidProperty))) .reduce(true, (acc, x) -> acc && x), "InvalidProperty constring not found!"); models.stream().forEach(type -> { final String subject = domain + "foo"; final Optional<ConstraintViolation> res = svc.constrainedBy(type, asGraph("/hasLdpContainsTriples.ttl", subject), domain) .filter(v -> v.getConstraint().equals(Trellis.InvalidProperty)).findFirst(); assertTrue(res.isPresent(), "Constraint violation not found!"); res.ifPresent(violation -> { assertEquals(Trellis.InvalidProperty, violation.getConstraint(), "no InvalidProperty violation!"); assertTrue(violation.getTriples().contains( rdf.createTriple(rdf.createIRI(subject), LDP.contains, rdf.createIRI(domain + "bar"))), "Triple missing from violation!"); }); }); }
@Test public void testBasicConstraints1() { final Optional<ConstraintViolation> res = svc.constrainedBy(LDP.Container, asGraph("/invalidContainer1.ttl", domain + "foo"), domain).findFirst(); assertTrue(res.isPresent(), "no constraint violation found!"); res.ifPresent(violation -> { assertEquals(Trellis.InvalidProperty, violation.getConstraint(), "no InvalidProperty violation!"); assertTrue(violation.getTriples().contains(rdf.createTriple(rdf.createIRI(domain + "foo"), LDP.isMemberOfRelation, rdf.createIRI(domain + "resource"))), "Triple not found in constraint violation!"); }); }
@Test public void testMembershipTriples1() { final Optional<ConstraintViolation> res = svc.constrainedBy(LDP.IndirectContainer, asGraph("/invalidMembershipTriple.ttl", domain + "foo"), domain) .filter(v -> v.getConstraint().equals(Trellis.InvalidRange)).findFirst(); assertTrue(res.isPresent(), "no constraint violation found!"); res.ifPresent(violation -> { assertEquals(Trellis.InvalidRange, violation.getConstraint(), "no InvalidRange violation!"); assertTrue(violation.getTriples().contains(rdf.createTriple(rdf.createIRI(domain + "foo"), LDP.hasMemberRelation, LDP.contains)), "Expected triple not found in violation!"); }); }
@Test public void testBasicConstraints3() { final Optional<ConstraintViolation> res = svc.constrainedBy(LDP.Container, asGraph("/invalidContainer3.ttl", domain + "foo"), domain).findFirst(); assertTrue(res.isPresent(), "no constraint violation found!"); res.ifPresent(violation -> { assertEquals(Trellis.InvalidProperty, violation.getConstraint(), "no InvalidProperty violation!"); assertTrue(violation.getTriples().contains(rdf.createTriple(rdf.createIRI(domain + "foo"), LDP.membershipResource, rdf.createIRI(domain + "resource"))), "Expected triple not found in violation!"); }); }
@Test public void testInvalidInbox() { final Optional<ConstraintViolation> res = svc.constrainedBy(LDP.RDFSource, asGraph("/invalidInbox.ttl", domain + "foo"), domain).findFirst(); assertTrue(res.isPresent(), "no constraint violation found!"); res.ifPresent(violation -> { assertEquals(Trellis.InvalidRange, violation.getConstraint(), "no InvalidRange constraint!"); assertTrue(violation.getTriples().contains(rdf.createTriple(rdf.createIRI(domain + "foo"), LDP.inbox, rdf.createLiteral("invalid range", "en"))), "Triple not found in constraint violation!"); }); }
@Test public void testBasicConstraints2() { final Optional<ConstraintViolation> res = svc.constrainedBy(LDP.Container, asGraph("/invalidContainer2.ttl", domain + "foo"), domain).findFirst(); assertTrue(res.isPresent(), "no constraint violation found!"); res.ifPresent(violation -> { assertEquals(Trellis.InvalidProperty, violation.getConstraint(), "no InvalidProperty violation!"); assertTrue(violation.getTriples().contains(rdf.createTriple(rdf.createIRI(domain + "foo"), LDP.insertedContentRelation, rdf.createIRI(domain + "resource"))), "Expected triple not found in violation!"); }); }