// TODO Merge arguments(acl, content)
  // FIXME Refactor duplicate isAllowableBaseType
  @Override
  public Boolean checkPermission(
      CallContext callContext,
      String repositoryId,
      String key,
      Acl acl,
      String baseType,
      Content content) {

    // All permission checks must go through baseType check
    if (!isAllowableBaseType(key, baseType, content, repositoryId)) return false;

    // Admin always pass a permission check
    CallContextImpl cci = (CallContextImpl) callContext;
    Boolean _isAdmin = (Boolean) cci.get(CallContextKey.IS_ADMIN);
    boolean isAdmin = (_isAdmin == null) ? false : _isAdmin;
    if (isAdmin) return true;

    // PWC doesn't accept any actions from a non-owner user
    // TODO admin can manipulate PWC even when it is checked out ?
    if (content.isDocument()) {
      Document document = (Document) content;
      if (document.isPrivateWorkingCopy()) {
        VersionSeries vs = contentService.getVersionSeries(repositoryId, document);
        if (!callContext.getUsername().equals(vs.getVersionSeriesCheckedOutBy())) {
          return false;
        }
      }
    }

    // Relation has no ACL stored in DB.
    // Though some actions are defined in the specs,
    // Some other direct actions is needed to be set here.
    if (content.isRelationship()) {
      Relationship relationship = (Relationship) content;
      return checkRelationshipPermission(callContext, repositoryId, key, relationship);
    }

    // Void Acl fails(but Admin can do an action)
    if (acl == null) return false;

    // Even if a user has multiple ACEs, the permissions is pushed into
    // Set<String> and remain unique.
    // Get ACL for the current user
    String userName = callContext.getUsername();
    List<Ace> aces = acl.getAllAces();
    Set<String> userPermissions = new HashSet<String>();
    Set<String> groups = principalService.getGroupIdsContainingUser(repositoryId, userName);
    for (Ace ace : aces) {
      // Filter ace which has not permissions
      if (ace.getPermissions() == null) continue;

      // Add user permissions
      if (ace.getPrincipalId().equals(userName)) {
        userPermissions.addAll(ace.getPermissions());
      }
      // Add inherited permissions which user inherits
      if (CollectionUtils.isNotEmpty(groups) && groups.contains(ace.getPrincipalId())) {
        userPermissions.addAll(ace.getPermissions());
      }
    }

    // Check mapping between the user and the content
    return checkCalculatedPermissions(repositoryId, key, userPermissions);
  }