// Path: fiat-core/src/main/java/com/netflix/spinnaker/fiat/model/resources/Role.java
// @Component
// @Data
// @EqualsAndHashCode(of = "name")
// @NoArgsConstructor
// public class Role implements Resource, Viewable {
// 
//   private final ResourceType resourceType = ResourceType.ROLE;
//   private String name;
// 
//   public enum Source {
//     EXTERNAL,
//     FILE,
//     GOOGLE_GROUPS,
//     GITHUB_TEAMS,
//     LDAP
//   }
// 
//   private Source source;
// 
//   public Role(String name) {
//     this.setName(name);
//   }
// 
//   public Role setName(@Nonnull String name) {
//     if (!StringUtils.hasText(name)) {
//       throw new IllegalArgumentException("name cannot be empty");
//     }
//     this.name = name.toLowerCase();
//     return this;
//   }
// 
//   @JsonIgnore
//   @Override
//   public View getView(Set<Role> ignored, boolean isAdmin) {
//     return new View(this);
//   }
// 
//   @Data
//   @EqualsAndHashCode(callSuper = false)
//   @NoArgsConstructor
//   public static class View extends BaseView {
//     private String name;
//     private Source source;
// 
//     public View(Role role) {
//       this.name = role.name;
//       this.source = role.getSource();
//     }
//   }
// }
// 
// Path: fiat-core/src/main/java/com/netflix/spinnaker/fiat/model/resources/ServiceAccount.java
// @Component
// @Data
// @EqualsAndHashCode(callSuper = false)
// public class ServiceAccount implements Resource, Viewable {
//   private final ResourceType resourceType = ResourceType.SERVICE_ACCOUNT;
// 
//   private String name;
//   private List<String> memberOf = new ArrayList<>();
// 
//   public UserPermission toUserPermission() {
//     val roles =
//         memberOf.stream()
//             .filter(StringUtils::hasText)
//             .map(membership -> new Role(membership).setSource(Role.Source.EXTERNAL))
//             .collect(Collectors.toSet());
//     return new UserPermission().setId(name).setRoles(roles);
//   }
// 
//   public ServiceAccount setMemberOf(List<String> membership) {
//     if (membership == null) {
//       membership = new ArrayList<>();
//     }
//     memberOf =
//         membership.stream().map(String::trim).map(String::toLowerCase).collect(Collectors.toList());
//     return this;
//   }
// 
//   @JsonIgnore
//   @Override
//   public View getView(Set<Role> ignored, boolean isAdmin) {
//     return new View(this);
//   }
// 
//   @Data
//   @EqualsAndHashCode(callSuper = false)
//   @NoArgsConstructor
//   public static class View extends BaseView {
//     private String name;
//     private List<String> memberOf;
// 
//     public View(ServiceAccount serviceAccount) {
//       this.name = serviceAccount.name;
//       this.memberOf = serviceAccount.memberOf;
//     }
//   }
// }


import com.netflix.spinnaker.fiat.config.FiatRoleConfig;
import com.netflix.spinnaker.fiat.model.resources.Role;
import com.netflix.spinnaker.fiat.model.resources.ServiceAccount;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import lombok.NonNull;
package com.netflix.spinnaker.fiat.providers;


public abstract class BaseServiceAccountResourceProvider
    extends BaseResourceProvider<ServiceAccount> {
  private final FiatRoleConfig fiatRoleConfig;

  public BaseServiceAccountResourceProvider(FiatRoleConfig fiatRoleConfig) {
    this.fiatRoleConfig = fiatRoleConfig;
  }

  @Override
  public Set<ServiceAccount> getAllRestricted(@NonNull Set<Role> roles, boolean isAdmin)
      throws ProviderException {
    List<String> roleNames = roles.stream().map(Role::getName).collect(Collectors.toList());
    return getAll().stream()
        .filter(svcAcct -> !svcAcct.getMemberOf().isEmpty())
        .filter(getServiceAccountPredicate(isAdmin, roleNames))
        .collect(Collectors.toSet());
  }

  private Predicate<ServiceAccount> getServiceAccountPredicate(
      boolean isAdmin, List<String> roleNames) {
    if (isAdmin) {
      return svcAcct -> true;
    }
    if (fiatRoleConfig.isOrMode()) {
      return svcAcct -> svcAcct.getMemberOf().stream().anyMatch(roleNames::contains);
    } else {
      return svcAcct -> roleNames.containsAll(svcAcct.getMemberOf());
    }
  }

// Path: fiat-core/src/main/java/com/netflix/spinnaker/fiat/model/resources/Role.java
// @Component
// @Data
// @EqualsAndHashCode(of = "name")
// @NoArgsConstructor
// public class Role implements Resource, Viewable {
// 
//   private final ResourceType resourceType = ResourceType.ROLE;
//   private String name;
// 
//   public enum Source {
//     EXTERNAL,
//     FILE,
//     GOOGLE_GROUPS,
//     GITHUB_TEAMS,
//     LDAP
//   }
// 
//   private Source source;
// 
//   public Role(String name) {
//     this.setName(name);
//   }
// 
//   public Role setName(@Nonnull String name) {
//     if (!StringUtils.hasText(name)) {
//       throw new IllegalArgumentException("name cannot be empty");
//     }
//     this.name = name.toLowerCase();
//     return this;
//   }
// 
//   @JsonIgnore
//   @Override
//   public View getView(Set<Role> ignored, boolean isAdmin) {
//     return new View(this);
//   }
// 
//   @Data
//   @EqualsAndHashCode(callSuper = false)
//   @NoArgsConstructor
//   public static class View extends BaseView {
//     private String name;
//     private Source source;
// 
//     public View(Role role) {
//       this.name = role.name;
//       this.source = role.getSource();
//     }
//   }
// }
// 
// Path: fiat-core/src/main/java/com/netflix/spinnaker/fiat/model/resources/ServiceAccount.java
// @Component
// @Data
// @EqualsAndHashCode(callSuper = false)
// public class ServiceAccount implements Resource, Viewable {
//   private final ResourceType resourceType = ResourceType.SERVICE_ACCOUNT;
// 
//   private String name;
//   private List<String> memberOf = new ArrayList<>();
// 
//   public UserPermission toUserPermission() {
//     val roles =
//         memberOf.stream()
//             .filter(StringUtils::hasText)
//             .map(membership -> new Role(membership).setSource(Role.Source.EXTERNAL))
//             .collect(Collectors.toSet());
//     return new UserPermission().setId(name).setRoles(roles);
//   }
// 
//   public ServiceAccount setMemberOf(List<String> membership) {
//     if (membership == null) {
//       membership = new ArrayList<>();
//     }
//     memberOf =
//         membership.stream().map(String::trim).map(String::toLowerCase).collect(Collectors.toList());
//     return this;
//   }
// 
//   @JsonIgnore
//   @Override
//   public View getView(Set<Role> ignored, boolean isAdmin) {
//     return new View(this);
//   }
// 
//   @Data
//   @EqualsAndHashCode(callSuper = false)
//   @NoArgsConstructor
//   public static class View extends BaseView {
//     private String name;
//     private List<String> memberOf;
// 
//     public View(ServiceAccount serviceAccount) {
//       this.name = serviceAccount.name;
//       this.memberOf = serviceAccount.memberOf;
//     }
//   }
// }


// Path: fiat-roles/src/main/java/com/netflix/spinnaker/fiat/providers/BaseServiceAccountResourceProvider.java
import com.netflix.spinnaker.fiat.config.FiatRoleConfig;
import com.netflix.spinnaker.fiat.model.resources.Role;
import com.netflix.spinnaker.fiat.model.resources.ServiceAccount;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import lombok.NonNull;

package com.netflix.spinnaker.fiat.providers;


public abstract class BaseServiceAccountResourceProvider
    extends BaseResourceProvider<ServiceAccount> {
  private final FiatRoleConfig fiatRoleConfig;

  public BaseServiceAccountResourceProvider(FiatRoleConfig fiatRoleConfig) {
    this.fiatRoleConfig = fiatRoleConfig;
  }

  @Override
  public Set<ServiceAccount> getAllRestricted(@NonNull Set<Role> roles, boolean isAdmin)
      throws ProviderException {
    List<String> roleNames = roles.stream().map(Role::getName).collect(Collectors.toList());
    return getAll().stream()
        .filter(svcAcct -> !svcAcct.getMemberOf().isEmpty())
        .filter(getServiceAccountPredicate(isAdmin, roleNames))
        .collect(Collectors.toSet());
  }

  private Predicate<ServiceAccount> getServiceAccountPredicate(
      boolean isAdmin, List<String> roleNames) {
    if (isAdmin) {
      return svcAcct -> true;
    }
    if (fiatRoleConfig.isOrMode()) {
      return svcAcct -> svcAcct.getMemberOf().stream().anyMatch(roleNames::contains);
    } else {
      return svcAcct -> roleNames.containsAll(svcAcct.getMemberOf());
    }
  }

  @Override