keith-turner commented on code in PR #34:
URL: https://github.com/apache/accumulo-access/pull/34#discussion_r1466703272


##########
src/main/java/org/apache/accumulo/access/AccessEvaluatorImpl.java:
##########
@@ -44,17 +43,33 @@ class AccessEvaluatorImpl implements AccessEvaluator {
   private final ThreadLocal<Tokenizer> tokenizers =
       ThreadLocal.withInitial(() -> new Tokenizer(EMPTY));
 
-  private AccessEvaluatorImpl(Authorizer authorizationChecker) {
+  AccessEvaluatorImpl(Authorizer authorizationChecker) {
     this.authorizedPredicates = List.of(auth -> 
authorizationChecker.isAuthorized(unescape(auth)));
   }
 
-  public AccessEvaluatorImpl(Collection<List<byte[]>> authorizationSets) {
-    authorizedPredicates = authorizationSets.stream()
-        .map(authorizations -> authorizations.stream()
-            .map(auth -> AccessEvaluatorImpl.escape(auth, 
false)).map(BytesWrapper::new)
-            .collect(toSet()))
-        .map(escapedAuths -> (Predicate<BytesWrapper>) escapedAuths::contains)
-        .collect(Collectors.toUnmodifiableList());
+  AccessEvaluatorImpl(final List<byte[]> authorizationSet) {
+    this(Collections.singletonList(authorizationSet));
+  }
+
+  AccessEvaluatorImpl(final Collection<List<byte[]>> authorizationSets) {
+
+    for (final List<byte[]> auths : authorizationSets) {
+      for (final byte[] auth : auths) {
+        if (auth.length == 0) {
+          throw new IllegalArgumentException("Empty authorization");
+        }
+      }
+    }
+
+    final List<Predicate<BytesWrapper>> predicates = new 
ArrayList<>(authorizationSets.size());
+    for (final List<byte[]> authorizationList : authorizationSets) {
+      final Set<BytesWrapper> authBytes = new 
HashSet<>(authorizationList.size());
+      for (final byte[] authorization : authorizationList) {
+        authBytes.add(new 
BytesWrapper(AccessEvaluatorImpl.escape(authorization, false)));
+      }
+      predicates.add((auth) -> authBytes.contains(auth));
+    }
+    authorizedPredicates = Collections.unmodifiableList(predicates);

Review Comment:
   Assuming authorizedPredicates is read a lot more frequently than its 
created, the following would be a bit more expensive to create but probably 
faster to read because there is less indirection.
   
   ```suggestion
       authorizedPredicates = List.copyOf(predicates);
   ```



##########
src/main/java/org/apache/accumulo/access/AccessEvaluator.java:
##########
@@ -74,88 +82,112 @@ public interface AccessEvaluator {
   boolean canAccess(AccessExpression accessExpression);
 
   /**
-   * An interface that is used to check if an authorization seen in an access 
expression is
-   * authorized.
+   * Creates an AccessEvaluator from an Authorizations object
    *
-   * @since 1.0.0
+   * @param authorizations auths to use in the AccessEvaluator
+   * @return AccessEvaluator object
    */
-  interface Authorizer {
-    boolean isAuthorized(String auth);
+  static AccessEvaluator of(Authorizations authorizations) {
+    final Set<String> authSet = authorizations.asSet();
+    final List<byte[]> authList = new ArrayList<>(authSet.size());
+    for (final String auth : authSet) {
+      authList.add(auth.getBytes(UTF_8));
+    }
+    return new AccessEvaluatorImpl(authList);
   }
 
-  interface AuthorizationsBuilder {
-
-    EvaluatorBuilder authorizations(Authorizations authorizations);
-
-    /**
-     * Allows providing multiple sets of authorizations. Each expression will 
be evaluated
-     * independently against each set of authorizations and will only be 
deemed accessible if
-     * accessible for all. For example the following code would print false, 
true, and then false.
-     *
-     * <pre>
-     *     {@code
-     * Collection<Authorizations> authSets =
-     *     List.of(Authorizations.of("A", "B"), Authorizations.of("C", "D"));
-     * var evaluator = 
AccessEvaluator.builder().authorizations(authSets).build();
-     *
-     * System.out.println(evaluator.canAccess("A"));
-     * System.out.println(evaluator.canAccess("A|D"));
-     * System.out.println(evaluator.canAccess("A&D"));
-     *
-     * }
-     * </pre>
-     *
-     * <p>
-     * The following table shows how each expression in the example above will 
evaluate for each
-     * authorization set. In order to return true for {@code canAccess()} the 
expression must
-     * evaluate to true for each authorization set.
-     *
-     * <table>
-     * <caption>Evaluations</caption>
-     * <tr>
-     * <td></td>
-     * <td>[A,B]</td>
-     * <td>[C,D]</td>
-     * </tr>
-     * <tr>
-     * <td>A</td>
-     * <td>True</td>
-     * <td>False</td>
-     * </tr>
-     * <tr>
-     * <td>A|D</td>
-     * <td>True</td>
-     * <td>True</td>
-     * </tr>
-     * <tr>
-     * <td>A&amp;D</td>
-     * <td>False</td>
-     * <td>False</td>
-     * </tr>
-     *
-     * </table>
-     *
-     *
-     *
-     */
-    EvaluatorBuilder authorizations(Collection<Authorizations> authorizations);
-
-    /**
-     * Allows specifying a single set of authorizations.
-     */
-    EvaluatorBuilder authorizations(String... authorizations);
+  /**
+   * Creates an AccessEvaluator from an Authorizer object
+   *
+   * @param authorizer authorizer to use in the AccessEvaluator
+   * @return AccessEvaluator object
+   */
+  static AccessEvaluator of(Authorizer authorizer) {
+    return new AccessEvaluatorImpl(authorizer);
+  }
 
-    /**
-     * Allows specifying an authorizer that is analogous to a single set of 
authorization.
-     */
-    EvaluatorBuilder authorizations(Authorizer authorizer);
+  /**
+   * Allows providing multiple sets of authorizations. Each expression will be 
evaluated
+   * independently against each set of authorizations and will only be deemed 
accessible if
+   * accessible for all. For example the following code would print false, 
true, and then false.
+   *
+   * <pre>
+   *     {@code
+   * Collection<Authorizations> authSets =
+   *     List.of(Authorizations.of("A", "B"), Authorizations.of("C", "D"));
+   * var evaluator = AccessEvaluator.of(authSets);
+   *
+   * System.out.println(evaluator.canAccess("A"));
+   * System.out.println(evaluator.canAccess("A|D"));
+   * System.out.println(evaluator.canAccess("A&D"));
+   *
+   * }
+   * </pre>
+   *
+   * <p>
+   * The following table shows how each expression in the example above will 
evaluate for each
+   * authorization set. In order to return true for {@code canAccess()} the 
expression must evaluate
+   * to true for each authorization set.
+   *
+   * <table>
+   * <caption>Evaluations</caption>
+   * <tr>
+   * <td></td>
+   * <td>[A,B]</td>
+   * <td>[C,D]</td>
+   * </tr>
+   * <tr>
+   * <td>A</td>
+   * <td>True</td>
+   * <td>False</td>
+   * </tr>
+   * <tr>
+   * <td>A|D</td>
+   * <td>True</td>
+   * <td>True</td>
+   * </tr>
+   * <tr>
+   * <td>A&amp;D</td>
+   * <td>False</td>
+   * <td>False</td>
+   * </tr>
+   *
+   * </table>
+   *
+   *
+   *
+   */
+  static AccessEvaluator of(Collection<Authorizations> authorizationSets) {
+    final List<List<byte[]>> authorizationLists = new 
ArrayList<>(authorizationSets.size());

Review Comment:
   I think its nice to minimize the code in the interface in order to make it 
easier for someone to quickly read the entire source code for the interface.  
Could push this into a static method in AccessEvaluatorImpl in order to 
minimize the size of the interface source code.  This is a style comment, so 
feel free to ignore.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to