Skip to content

Commit a925be6

Browse files
committed
Additional high-level API
1 parent e0719eb commit a925be6

File tree

2 files changed

+83
-15
lines changed

2 files changed

+83
-15
lines changed

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

Lines changed: 78 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@
3030
import java.util.Set;
3131
import java.util.UUID;
3232
import java.util.function.Consumer;
33+
import java.util.stream.Collectors;
3334

3435
import org.apache.commons.rdf.api.Dataset;
3536
import org.apache.commons.rdf.api.Graph;
37+
import org.apache.commons.rdf.api.IRI;
3638
import org.apache.commons.rdf.api.Quad;
3739
import org.apache.commons.rdf.api.RDFTerm;
3840

@@ -51,8 +53,7 @@ public class AccessControlResource extends RDFSource {
5153
*/
5254
public AccessControlResource(final URI identifier, final Dataset dataset) {
5355
super(identifier, dataset);
54-
dataset.add(null, rdf.createIRI(identifier.toString()), rdf.createIRI(RDF.type.toString()),
55-
rdf.createIRI(ACP.AccessControlResource.toString()));
56+
dataset.add(null, asIRI(identifier), asIRI(RDF.type), asIRI(ACP.AccessControlResource));
5657
}
5758

5859
/**
@@ -63,7 +64,7 @@ public AccessControlResource(final URI identifier, final Dataset dataset) {
6364
* @return a collection of {@link AccessControl} objects
6465
*/
6566
public Set<AccessControl> accessControl() {
66-
return new ACPNode(rdf.createIRI(getIdentifier().toString()), getGraph()).accessControl();
67+
return new ACPNode(asIRI(getIdentifier()), getGraph()).accessControl();
6768
}
6869

6970
/**
@@ -74,15 +75,15 @@ public Set<AccessControl> accessControl() {
7475
* @return a collection of {@link AccessControl} objects
7576
*/
7677
public Set<AccessControl> memberAccessControl() {
77-
return new ACPNode(rdf.createIRI(getIdentifier().toString()), getGraph()).memberAccessControl();
78+
return new ACPNode(asIRI(getIdentifier()), getGraph()).memberAccessControl();
7879
}
7980

8081
/**
8182
* Compact the internal data.
8283
*/
8384
public void compact() {
84-
final var accessControls = stream(null, null, rdf.createIRI(RDF.type.toString()),
85-
rdf.createIRI(ACP.AccessControl.toString())).map(Quad::getSubject).toList();
85+
final var accessControls = stream(null, null, asIRI(RDF.type), asIRI(ACP.AccessControl))
86+
.map(Quad::getSubject).toList();
8687
for (final var accessControl : accessControls) {
8788
if (!contains(null, null, null, accessControl)) {
8889
for (final var quad : stream(null, accessControl, null, null).toList()) {
@@ -91,8 +92,7 @@ public void compact() {
9192
}
9293
}
9394

94-
final var policies = stream(null, null, rdf.createIRI(RDF.type.toString()),
95-
rdf.createIRI(ACP.Policy.toString())).map(Quad::getSubject).toList();
95+
final var policies = stream(null, null, asIRI(RDF.type), asIRI(ACP.Policy)).map(Quad::getSubject).toList();
9696
for (final var policy : policies) {
9797
if (!contains(null, null, null, policy)) {
9898
for (final var quad : stream(null, policy, null, null).toList()) {
@@ -101,8 +101,7 @@ public void compact() {
101101
}
102102
}
103103

104-
final var matchers = stream(null, null, rdf.createIRI(RDF.type.toString()),
105-
rdf.createIRI(ACP.Matcher.toString())).map(Quad::getSubject).toList();
104+
final var matchers = stream(null, null, asIRI(RDF.type), asIRI(ACP.Matcher)).map(Quad::getSubject).toList();
106105
for (final var matcher : matchers) {
107106
if (!contains(null, null, null, matcher)) {
108107
for (final var quad : stream(null, matcher, null, null).toList()) {
@@ -112,18 +111,74 @@ public void compact() {
112111
}
113112
}
114113

114+
/**
115+
* Merge two or more policies into a single policies with combined matchers.
116+
*
117+
* @param policies the policies to merge
118+
* @return the merged policy
119+
*/
120+
public Policy merge(final Policy... policies) {
121+
final var baseUri = getIdentifier().getScheme() + ":" + getIdentifier().getSchemeSpecificPart();
122+
final var policy = new Policy(asIRI(baseUri + "#" + UUID.randomUUID()), getGraph());
123+
for (final var p : policies) {
124+
policy.allOf().addAll(p.allOf());
125+
policy.anyOf().addAll(p.anyOf());
126+
policy.noneOf().addAll(p.noneOf());
127+
}
128+
return policy;
129+
}
130+
131+
public enum MatcherType {
132+
AGENT(ACP.agent), CLIENT(ACP.client), ISSUER(ACP.issuer), VC(ACP.vc);
133+
134+
private final URI predicate;
135+
136+
MatcherType(final URI predicate) {
137+
this.predicate = predicate;
138+
}
139+
140+
public IRI asIRI() {
141+
return AccessControlResource.asIRI(predicate);
142+
}
143+
144+
public URI asURI() {
145+
return predicate;
146+
}
147+
}
148+
149+
/**
150+
* Find a policy, given a type, value and set of modes.
151+
*
152+
* @param type the matcher type
153+
* @param value the matcher value
154+
* @param modes the expected modes of the enclosing policy
155+
* @return the matched policies
156+
*/
157+
public Set<Policy> find(final MatcherType type, final URI value, final Set<URI> modes) {
158+
return stream(null, null, type.asIRI(), asIRI(value))
159+
.map(Quad::getSubject)
160+
.flatMap(matcher -> stream(null, null, null, matcher))
161+
.map(Quad::getSubject)
162+
.filter(policy -> contains(null, policy, asIRI(RDF.type), asIRI(ACP.Policy)))
163+
.filter(policy -> stream(null, policy, asIRI(ACP.allow), null)
164+
.map(Quad::getObject).filter(IRI.class::isInstance).map(IRI.class::cast)
165+
.map(IRI::getIRIString).map(URI::create).toList().containsAll(modes))
166+
.map(policy -> new Policy(policy, getGraph()))
167+
.collect(Collectors.toSet());
168+
}
169+
115170
static class ACPNode extends WrapperIRI {
116171
public ACPNode(final RDFTerm original, final Graph graph) {
117172
super(original, graph);
118173
}
119174

120175
public Set<AccessControl> memberAccessControl() {
121-
return objects(rdf.createIRI(ACP.memberAccessControl.toString()),
176+
return objects(asIRI(ACP.memberAccessControl),
122177
AccessControl::asResource, ValueMappings.as(AccessControl.class));
123178
}
124179

125180
public Set<AccessControl> accessControl() {
126-
return objects(rdf.createIRI(ACP.accessControl.toString()),
181+
return objects(asIRI(ACP.accessControl),
127182
AccessControl::asResource, ValueMappings.as(AccessControl.class));
128183
}
129184
}
@@ -136,7 +191,7 @@ public Set<AccessControl> accessControl() {
136191
*/
137192
public AccessControl accessControl(final Policy... policies) {
138193
final var baseUri = getIdentifier().getScheme() + ":" + getIdentifier().getSchemeSpecificPart();
139-
final var ac = new AccessControl(rdf.createIRI(baseUri + "#" + UUID.randomUUID()), getGraph());
194+
final var ac = new AccessControl(asIRI(baseUri + "#" + UUID.randomUUID()), getGraph());
140195
for (final var policy : policies) {
141196
ac.apply().add(policy);
142197
}
@@ -228,14 +283,22 @@ public Policy issuerPolicy(final URI issuer, final URI... access) {
228283

229284
Policy simplePolicy(final Consumer<Matcher> handler, final URI... access) {
230285
final var baseUri = getIdentifier().getScheme() + ":" + getIdentifier().getSchemeSpecificPart();
231-
final var matcher = new Matcher(rdf.createIRI(baseUri + "#" + UUID.randomUUID()), getGraph());
286+
final var matcher = new Matcher(asIRI(baseUri + "#" + UUID.randomUUID()), getGraph());
232287
handler.accept(matcher);
233288

234-
final var policy = new Policy(rdf.createIRI(baseUri + "#" + UUID.randomUUID()), getGraph());
289+
final var policy = new Policy(asIRI(baseUri + "#" + UUID.randomUUID()), getGraph());
235290
for (final var item : access) {
236291
policy.allow().add(item);
237292
}
238293
policy.allOf().add(matcher);
239294
return policy;
240295
}
296+
297+
private static IRI asIRI(final URI uri) {
298+
return asIRI(uri.toString());
299+
}
300+
301+
private static IRI asIRI(final String uri) {
302+
return rdf.createIRI(uri);
303+
}
241304
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ public Set<Matcher> anyOf() {
7070
Matcher::asResource, ValueMappings.as(Matcher.class));
7171
}
7272

73+
public Set<Matcher> noneOf() {
74+
return objects(rdf.createIRI(ACP.noneOf.toString()),
75+
Matcher::asResource, ValueMappings.as(Matcher.class));
76+
}
77+
7378
public Set<URI> allow() {
7479
return objects(rdf.createIRI(ACP.allow.toString()),
7580
TermMappings::asIri, ValueMappings::iriAsUri);

0 commit comments

Comments
 (0)