@@ -390,6 +390,28 @@ public CompletionStage<AccessCredentialVerification> verify(final AccessCredenti
390390 */
391391 public <T extends AccessCredential > CompletionStage <List <T >> query (final URI resource , final URI creator ,
392392 final URI recipient , final URI purpose , final String mode , final Class <T > clazz ) {
393+
394+ final Set <String > modes = mode != null ? Collections .singleton (mode ) : Collections .emptySet ();
395+ final Set <URI > purposes = purpose != null ? Collections .singleton (purpose ) : Collections .emptySet ();
396+
397+ return query (resource , creator , recipient , purposes , modes , clazz );
398+ }
399+
400+ /**
401+ * Perform an Access Grant query.
402+ *
403+ * @param <T> the AccessCredential type
404+ * @param query the access credential query, never {@code null}
405+ * @return the next stage of completion, including the matched Access Credentials
406+ */
407+ public <T extends AccessCredential > CompletionStage <List <T >> query (final AccessCredentialQuery <T > query ) {
408+ Objects .requireNonNull (query , "The query may not be null!" );
409+ return query (query .getResource (), query .getCreator (), query .getRecipient (), query .getPurposes (),
410+ query .getModes (), query .getAccessCredentialType ());
411+ }
412+
413+ private <T extends AccessCredential > CompletionStage <List <T >> query (final URI resource , final URI creator ,
414+ final URI recipient , final Set <URI > purposes , final Set <String > modes , final Class <T > clazz ) {
393415 Objects .requireNonNull (clazz , "The clazz parameter must not be null!" );
394416
395417 final URI type ;
@@ -409,7 +431,7 @@ public <T extends AccessCredential> CompletionStage<List<T>> query(final URI res
409431
410432 return v1Metadata ().thenCompose (metadata -> {
411433 final List <CompletableFuture <List <T >>> futures = buildQuery (config .getIssuer (), type ,
412- resource , creator , recipient , purpose , mode ).stream ()
434+ resource , creator , recipient , purposes , modes ).stream ()
413435 .map (data -> Request .newBuilder (metadata .queryEndpoint )
414436 .header (CONTENT_TYPE , APPLICATION_JSON )
415437 .POST (Request .BodyPublishers .ofByteArray (serialize (data ))).build ())
@@ -455,7 +477,7 @@ public CompletionStage<List<AccessGrant>> query(final URI type, final URI agent,
455477 Objects .requireNonNull (type , "The type parameter must not be null!" );
456478 return v1Metadata ().thenCompose (metadata -> {
457479 final List <CompletableFuture <List <AccessGrant >>> futures = buildQuery (config .getIssuer (), type ,
458- resource , null , agent , null , mode ).stream ()
480+ resource , null , agent , Collections . emptySet (), Collections . singleton ( mode ) ).stream ()
459481 .map (data -> Request .newBuilder (metadata .queryEndpoint )
460482 .header (CONTENT_TYPE , APPLICATION_JSON )
461483 .POST (Request .BodyPublishers .ofByteArray (serialize (data ))).build ())
@@ -688,14 +710,15 @@ static Collection<Object> getCredentials(final Map<String, Object> data) {
688710 }
689711
690712 static List <Map <String , Object >> buildQuery (final URI issuer , final URI type , final URI resource , final URI creator ,
691- final URI recipient , final URI purpose , final String mode ) {
713+ final URI recipient , final Set < URI > purposes , final Set < String > modes ) {
692714 final List <Map <String , Object >> queries = new ArrayList <>();
693- buildQuery (queries , issuer , type , resource , creator , recipient , purpose , mode );
715+ buildQuery (queries , issuer , type , resource , creator , recipient , purposes , modes );
694716 return queries ;
695717 }
696718
697719 static void buildQuery (final List <Map <String , Object >> queries , final URI issuer , final URI type ,
698- final URI resource , final URI creator , final URI recipient , final URI purpose , final String mode ) {
720+ final URI resource , final URI creator , final URI recipient , final Set <URI > purposes ,
721+ final Set <String > modes ) {
699722 final Map <String , Object > credential = new HashMap <>();
700723 credential .put (CONTEXT , Arrays .asList (VC_CONTEXT_URI , INRUPT_CONTEXT_URI ));
701724 credential .put ("issuer" , issuer );
@@ -706,7 +729,7 @@ static void buildQuery(final List<Map<String, Object>> queries, final URI issuer
706729 subject .put ("id" , creator );
707730 }
708731
709- final Map <String , Object > consent = buildConsent (type , resource , recipient , purpose , mode );
732+ final Map <String , Object > consent = buildConsent (type , resource , recipient , purposes , modes );
710733 if (!consent .isEmpty ()) {
711734 if (isAccessGrant (type ) || isAccessDenial (type )) {
712735 subject .put (PROVIDED_CONSENT , consent );
@@ -726,12 +749,12 @@ static void buildQuery(final List<Map<String, Object>> queries, final URI issuer
726749 // Recurse
727750 final URI parent = getParent (resource );
728751 if (parent != null ) {
729- buildQuery (queries , issuer , type , parent , creator , recipient , purpose , mode );
752+ buildQuery (queries , issuer , type , parent , creator , recipient , purposes , modes );
730753 }
731754 }
732755
733- static Map <String , Object > buildConsent (final URI type , final URI resource , final URI recipient , final URI purpose ,
734- final String mode ) {
756+ static Map <String , Object > buildConsent (final URI type , final URI resource , final URI recipient ,
757+ final Set < URI > purposes , final Set < String > modes ) {
735758 final Map <String , Object > consent = new HashMap <>();
736759 if (recipient != null ) {
737760 if (isAccessGrant (type ) || isAccessDenial (type )) {
@@ -743,11 +766,11 @@ static Map<String, Object> buildConsent(final URI type, final URI resource, fina
743766 if (resource != null ) {
744767 consent .put (FOR_PERSONAL_DATA , resource );
745768 }
746- if (purpose != null ) {
747- consent .put (FOR_PURPOSE , purpose );
769+ if (! purposes . isEmpty () ) {
770+ consent .put (FOR_PURPOSE , purposes );
748771 }
749- if (mode != null ) {
750- consent .put (MODE , mode );
772+ if (! modes . isEmpty () ) {
773+ consent .put (MODE , modes );
751774 }
752775 return consent ;
753776 }
0 commit comments