Skip to content

Commit 3348ae8

Browse files
committed
Add documentation
1 parent f82fd98 commit 3348ae8

File tree

6 files changed

+313
-173
lines changed

6 files changed

+313
-173
lines changed

acp/src/main/java/com/inrupt/client/acp/AccessControl.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.apache.commons.rdf.api.RDF;
3535
import org.apache.commons.rdf.api.RDFTerm;
3636

37+
3738
public class AccessControl extends WrapperIRI {
3839

3940
static final RDF rdf = RDFFactory.getInstance();
@@ -43,7 +44,12 @@ public AccessControl(final RDFTerm original, final Graph graph) {
4344
graph.add((IRI) original, rdf.createIRI(type.toString()), rdf.createIRI(ACP.AccessControl.toString()));
4445
}
4546

46-
public static IRI asResource(final AccessControl accessControl, final Graph graph) {
47+
public Set<Policy> apply() {
48+
return objects(rdf.createIRI(ACP.apply.toString()),
49+
Policy::asResource, ValueMappings.as(Policy.class));
50+
}
51+
52+
static IRI asResource(final AccessControl accessControl, final Graph graph) {
4753
graph.add(accessControl, rdf.createIRI(type.toString()), rdf.createIRI(ACP.AccessControl.toString()));
4854
accessControl.apply().forEach(policy -> {
4955
graph.add(accessControl, rdf.createIRI(ACP.apply.toString()), policy);
@@ -52,10 +58,5 @@ public static IRI asResource(final AccessControl accessControl, final Graph grap
5258

5359
return accessControl;
5460
}
55-
56-
public Set<Policy> apply() {
57-
return objects(rdf.createIRI(ACP.apply.toString()),
58-
Policy::asResource, ValueMappings.as(Policy.class));
59-
}
6061
}
6162

acp/src/main/java/com/inrupt/client/acp/AccessControlResource.java

Lines changed: 144 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,46 @@
4545

4646
/**
4747
* An Access Control Resource type.
48+
*
49+
* <p>This is the root type for a resource that expresses access control policies.
4850
*/
4951
public class AccessControlResource extends RDFSource {
5052

5153
private static final Logger LOGGER = LoggerFactory.getLogger(AccessControlResource.class);
5254

5355
public static final URI SOLID_ACCESS_GRANT = URI.create("http://www.w3.org/ns/solid/vc#SolidAccessGrant");
5456

57+
/**
58+
* Definitions for different matcher types, for use with {@link #find}.
59+
*/
60+
public enum MatcherType {
61+
AGENT(ACP.agent), CLIENT(ACP.client), ISSUER(ACP.issuer), VC(ACP.vc);
62+
63+
private final URI predicate;
64+
65+
MatcherType(final URI predicate) {
66+
this.predicate = predicate;
67+
}
68+
69+
/**
70+
* Return the matcher type as an IRI.
71+
*
72+
* @return the IRI for this predicate
73+
*/
74+
public IRI asIRI() {
75+
return AccessControlResource.asIRI(asURI());
76+
}
77+
78+
/**
79+
* Return the matcher type as a URI.
80+
*
81+
* @return the URI for this predicate
82+
*/
83+
public URI asURI() {
84+
return predicate;
85+
}
86+
}
87+
5588
/**
5689
* Create a new Access Control Resource.
5790
*
@@ -94,17 +127,26 @@ public Set<AccessControl> memberAccessControl() {
94127
public AccessControlResource expand(final SolidSyncClient client) {
95128
// Copy the data from the existing ACR into a new dataset
96129
final var dataset = rdf.createDataset();
130+
final var matcherType = asIRI(ACP.Matcher);
131+
final var accessControlType = asIRI(ACP.AccessControl);
97132
stream().forEach(dataset::add);
98133

99-
final var cache = rdf.createDataset();
100-
expandType(dataset, cache, asIRI(ACP.accessControl), asIRI(ACP.AccessControl),
101-
uri -> populateCache(client, uri, cache));
102-
expandType(dataset, cache, asIRI(ACP.memberAccessControl), asIRI(ACP.AccessControl),
103-
uri -> populateCache(client, uri, cache));
104-
expandType(dataset, cache, asIRI(ACP.apply), asIRI(ACP.Policy), uri -> populateCache(client, uri, cache));
105-
expandType(dataset, cache, asIRI(ACP.allOf), asIRI(ACP.Matcher), uri -> populateCache(client, uri, cache));
106-
expandType(dataset, cache, asIRI(ACP.anyOf), asIRI(ACP.Matcher), uri -> populateCache(client, uri, cache));
107-
expandType(dataset, cache, asIRI(ACP.noneOf), asIRI(ACP.Matcher), uri -> populateCache(client, uri, cache));
134+
try (final var cache = rdf.createDataset()) {
135+
expandType(dataset, cache, asIRI(ACP.accessControl), accessControlType,
136+
uri -> populateCache(client, uri, cache));
137+
expandType(dataset, cache, asIRI(ACP.memberAccessControl), accessControlType,
138+
uri -> populateCache(client, uri, cache));
139+
expandType(dataset, cache, asIRI(ACP.apply), asIRI(ACP.Policy),
140+
uri -> populateCache(client, uri, cache));
141+
expandType(dataset, cache, asIRI(ACP.allOf), matcherType,
142+
uri -> populateCache(client, uri, cache));
143+
expandType(dataset, cache, asIRI(ACP.anyOf), matcherType,
144+
uri -> populateCache(client, uri, cache));
145+
expandType(dataset, cache, asIRI(ACP.noneOf), matcherType,
146+
uri -> populateCache(client, uri, cache));
147+
} catch (final Exception ex) {
148+
LOGGER.atDebug().setMessage("Unable to close dataset: {}").addArgument(ex::getMessage).log();
149+
}
108150

109151
return new AccessControlResource(getIdentifier(), dataset);
110152
}
@@ -120,67 +162,26 @@ public AccessControlResource expand(final SolidClient client) {
120162
final var dataset = rdf.createDataset();
121163
stream().forEach(dataset::add);
122164

123-
final var cache = rdf.createDataset();
124-
expandType(dataset, cache, asIRI(ACP.accessControl), asIRI(ACP.AccessControl),
125-
uri -> populateCache(client, uri, cache));
126-
expandType(dataset, cache, asIRI(ACP.memberAccessControl), asIRI(ACP.AccessControl),
127-
uri -> populateCache(client, uri, cache));
128-
expandType(dataset, cache, asIRI(ACP.apply), asIRI(ACP.Policy), uri -> populateCache(client, uri, cache));
129-
expandType(dataset, cache, asIRI(ACP.allOf), asIRI(ACP.Matcher), uri -> populateCache(client, uri, cache));
130-
expandType(dataset, cache, asIRI(ACP.anyOf), asIRI(ACP.Matcher), uri -> populateCache(client, uri, cache));
131-
expandType(dataset, cache, asIRI(ACP.noneOf), asIRI(ACP.Matcher), uri -> populateCache(client, uri, cache));
132-
133-
return new AccessControlResource(getIdentifier(), dataset);
134-
}
135-
136-
void expandType(final Dataset dataset, final Dataset cache, final IRI predicate, final IRI type,
137-
final Consumer<URI> handler) {
138-
final var subjects = dataset.stream(null, null, predicate, null)
139-
.map(Quad::getObject).filter(IRI.class::isInstance).map(IRI.class::cast)
140-
.filter(subject -> !dataset.contains(null, subject, asIRI(RDF.type), type)).toList();
141-
142-
for (final var subject : subjects) {
143-
if (!cache.contains(null, subject, asIRI(RDF.type), type)) {
144-
handler.accept(URI.create(subject.getIRIString()));
145-
}
146-
cache.stream(null, subject, null, null).forEach(dataset::add);
147-
}
148-
}
149-
150-
void populateCache(final SolidSyncClient client, final URI uri, final Dataset cache) {
151-
try (final var acr = client.read(uri, AccessControlResource.class)) {
152-
acr.stream()
153-
.filter(quad -> !isAccessControlResourceType(quad))
154-
.forEach(cache::add);
165+
final var matcherType = asIRI(ACP.Matcher);
166+
final var accessControlType = asIRI(ACP.AccessControl);
167+
try (final var cache = rdf.createDataset()) {
168+
expandType(dataset, cache, asIRI(ACP.accessControl), accessControlType,
169+
uri -> populateCacheAsync(client, uri, cache));
170+
expandType(dataset, cache, asIRI(ACP.memberAccessControl), accessControlType,
171+
uri -> populateCacheAsync(client, uri, cache));
172+
expandType(dataset, cache, asIRI(ACP.apply), asIRI(ACP.Policy),
173+
uri -> populateCacheAsync(client, uri, cache));
174+
expandType(dataset, cache, asIRI(ACP.allOf), matcherType,
175+
uri -> populateCacheAsync(client, uri, cache));
176+
expandType(dataset, cache, asIRI(ACP.anyOf), matcherType,
177+
uri -> populateCacheAsync(client, uri, cache));
178+
expandType(dataset, cache, asIRI(ACP.noneOf), matcherType,
179+
uri -> populateCacheAsync(client, uri, cache));
155180
} catch (final Exception ex) {
156-
LOGGER.atDebug()
157-
.setMessage("Unable to fetch access control resource from {}: {}")
158-
.addArgument(uri)
159-
.addArgument(ex::getMessage)
160-
.log();
181+
LOGGER.atDebug().setMessage("Unable to close dataset: {}").addArgument(ex::getMessage).log();
161182
}
162-
}
163-
164-
void populateCache(final SolidClient client, final URI uri, final Dataset cache) {
165-
client.read(uri, AccessControlResource.class).thenAccept(res -> {
166-
try (final var acr = res) {
167-
acr.stream()
168-
.filter(quad -> !isAccessControlResourceType(quad))
169-
.forEach(cache::add);
170-
}
171-
})
172-
.exceptionally(err -> {
173-
LOGGER.atDebug()
174-
.setMessage("Unable to fetch access control resource from {}: {}")
175-
.addArgument(uri)
176-
.addArgument(err::getMessage)
177-
.log();
178-
return null;
179-
}).toCompletableFuture().join();
180-
}
181183

182-
static boolean isAccessControlResourceType(final Quad quad) {
183-
return asIRI(RDF.type).equals(quad.getPredicate()) && asIRI(ACP.AccessControlResource).equals(quad.getObject());
184+
return new AccessControlResource(getIdentifier(), dataset);
184185
}
185186

186187
/**
@@ -204,14 +205,6 @@ public void compact() {
204205
}
205206
}
206207

207-
<T extends BlankNodeOrIRI> void removeUnusedStatements(final T resource) {
208-
if (!contains(null, null, null, resource)) {
209-
for (final var quad : stream(null, resource, null, null).toList()) {
210-
remove(quad);
211-
}
212-
}
213-
}
214-
215208
/**
216209
* Merge two or more policies into a single policies with combined matchers.
217210
*
@@ -229,24 +222,6 @@ public Policy merge(final Policy... policies) {
229222
return policy;
230223
}
231224

232-
public enum MatcherType {
233-
AGENT(ACP.agent), CLIENT(ACP.client), ISSUER(ACP.issuer), VC(ACP.vc);
234-
235-
private final URI predicate;
236-
237-
MatcherType(final URI predicate) {
238-
this.predicate = predicate;
239-
}
240-
241-
public IRI asIRI() {
242-
return AccessControlResource.asIRI(asURI());
243-
}
244-
245-
public URI asURI() {
246-
return predicate;
247-
}
248-
}
249-
250225
/**
251226
* Find a policy, given a type, value and set of modes.
252227
*
@@ -268,22 +243,6 @@ public Set<Policy> find(final MatcherType type, final URI value, final Set<URI>
268243
.collect(Collectors.toSet());
269244
}
270245

271-
static class ACPNode extends WrapperIRI {
272-
public ACPNode(final RDFTerm original, final Graph graph) {
273-
super(original, graph);
274-
}
275-
276-
public Set<AccessControl> memberAccessControl() {
277-
return objects(asIRI(ACP.memberAccessControl),
278-
AccessControl::asResource, ValueMappings.as(AccessControl.class));
279-
}
280-
281-
public Set<AccessControl> accessControl() {
282-
return objects(asIRI(ACP.accessControl),
283-
AccessControl::asResource, ValueMappings.as(AccessControl.class));
284-
}
285-
}
286-
287246
/**
288247
* Add policies to the access control resource.
289248
*
@@ -382,6 +341,22 @@ public Policy issuerPolicy(final URI issuer, final URI... access) {
382341
return simplePolicy(matcher -> matcher.issuer().add(issuer), access);
383342
}
384343

344+
static class ACPNode extends WrapperIRI {
345+
public ACPNode(final RDFTerm original, final Graph graph) {
346+
super(original, graph);
347+
}
348+
349+
public Set<AccessControl> memberAccessControl() {
350+
return objects(asIRI(ACP.memberAccessControl),
351+
AccessControl::asResource, ValueMappings.as(AccessControl.class));
352+
}
353+
354+
public Set<AccessControl> accessControl() {
355+
return objects(asIRI(ACP.accessControl),
356+
AccessControl::asResource, ValueMappings.as(AccessControl.class));
357+
}
358+
}
359+
385360
Policy simplePolicy(final Consumer<Matcher> handler, final URI... access) {
386361
final var baseUri = getIdentifier().getScheme() + ":" + getIdentifier().getSchemeSpecificPart();
387362
final var matcher = new Matcher(asIRI(baseUri + "#" + UUID.randomUUID()), getGraph());
@@ -395,11 +370,69 @@ Policy simplePolicy(final Consumer<Matcher> handler, final URI... access) {
395370
return policy;
396371
}
397372

398-
private static IRI asIRI(final URI uri) {
373+
<T extends BlankNodeOrIRI> void removeUnusedStatements(final T resource) {
374+
if (!contains(null, null, null, resource)) {
375+
for (final var quad : stream(null, resource, null, null).toList()) {
376+
remove(quad);
377+
}
378+
}
379+
}
380+
381+
void expandType(final Dataset dataset, final Dataset cache, final IRI predicate, final IRI type,
382+
final Consumer<URI> handler) {
383+
final var subjects = dataset.stream(null, null, predicate, null)
384+
.map(Quad::getObject).filter(IRI.class::isInstance).map(IRI.class::cast)
385+
.filter(subject -> !dataset.contains(null, subject, asIRI(RDF.type), type)).toList();
386+
387+
for (final var subject : subjects) {
388+
if (!cache.contains(null, subject, asIRI(RDF.type), type)) {
389+
handler.accept(URI.create(subject.getIRIString()));
390+
}
391+
cache.stream(null, subject, null, null).forEach(dataset::add);
392+
}
393+
}
394+
395+
void populateCache(final SolidSyncClient client, final URI uri, final Dataset cache) {
396+
try (final var acr = client.read(uri, AccessControlResource.class)) {
397+
acr.stream()
398+
.filter(quad -> !isAccessControlResourceType(quad))
399+
.forEach(cache::add);
400+
} catch (final Exception ex) {
401+
LOGGER.atDebug()
402+
.setMessage("Unable to fetch access control resource from {}: {}")
403+
.addArgument(uri)
404+
.addArgument(ex::getMessage)
405+
.log();
406+
}
407+
}
408+
409+
void populateCacheAsync(final SolidClient client, final URI uri, final Dataset cache) {
410+
client.read(uri, AccessControlResource.class).thenAccept(res -> {
411+
try (final var acr = res) {
412+
acr.stream()
413+
.filter(quad -> !isAccessControlResourceType(quad))
414+
.forEach(cache::add);
415+
}
416+
})
417+
.exceptionally(err -> {
418+
LOGGER.atDebug()
419+
.setMessage("Unable to fetch access control resource from {}: {}")
420+
.addArgument(uri)
421+
.addArgument(err::getMessage)
422+
.log();
423+
return null;
424+
}).toCompletableFuture().join();
425+
}
426+
427+
static boolean isAccessControlResourceType(final Quad quad) {
428+
return asIRI(RDF.type).equals(quad.getPredicate()) && asIRI(ACP.AccessControlResource).equals(quad.getObject());
429+
}
430+
431+
static IRI asIRI(final URI uri) {
399432
return asIRI(uri.toString());
400433
}
401434

402-
private static IRI asIRI(final String uri) {
435+
static IRI asIRI(final String uri) {
403436
return rdf.createIRI(uri);
404437
}
405438
}

0 commit comments

Comments
 (0)