@Override
 public void constraintAlreadyCheckedOut(String repositoryId, Document document) {
   VersionSeries vs = contentService.getVersionSeries(repositoryId, document);
   if (vs.isVersionSeriesCheckedOut()) {
     if (!(document.isPrivateWorkingCopy())) {
       constraint(document.getId(), "The version series is already checked out");
     }
   }
 }
  @Override
  public ObjectData getObject(
      CallContext callContext,
      String repositoryId,
      String objectId,
      String filter,
      Boolean includeAllowableActions,
      IncludeRelationships includeRelationships,
      String renditionFilter,
      Boolean includePolicyIds,
      Boolean includeAcl,
      ExtensionsData extension) {

    exceptionService.invalidArgumentRequired("objectId", objectId);

    Lock lock = threadLockService.getReadLock(repositoryId, objectId);
    try {
      lock.lock();

      // //////////////////
      // General Exception
      // //////////////////
      Content content = contentService.getContent(repositoryId, objectId);
      // WORK AROUND: getObject(versionSeriesId) is interpreted as
      // getDocumentOflatestVersion
      if (content == null) {
        VersionSeries versionSeries = contentService.getVersionSeries(repositoryId, objectId);
        if (versionSeries != null) {
          content = contentService.getDocumentOfLatestVersion(repositoryId, objectId);
        }
      }
      exceptionService.objectNotFound(DomainType.OBJECT, content, objectId);
      exceptionService.permissionDenied(
          callContext, repositoryId, PermissionMapping.CAN_GET_PROPERTIES_OBJECT, content);

      // //////////////////
      // Body of the method
      // //////////////////
      ObjectData object =
          compileService.compileObjectData(
              callContext,
              repositoryId,
              content,
              filter,
              includeAllowableActions,
              includeRelationships,
              null,
              includeAcl);

      return object;
    } finally {
      lock.unlock();
    }
  }
 @Override
 public void constraintUpdateWhenCheckedOut(
     String repositoryId, String currentUserId, Document document) {
   VersionSeries vs = contentService.getVersionSeries(repositoryId, document);
   if (vs.isVersionSeriesCheckedOut()) {
     if (document.isPrivateWorkingCopy()) {
       // Can update by only the use who has checked it out
       String whoCheckedOut = vs.getVersionSeriesCheckedOutBy();
       if (!currentUserId.equals(whoCheckedOut)) {
         constraint(
             document.getId(),
             "This private working copy can be modified only by the user who has checked it out. ");
       }
     } else {
       // All versions except for PWC are locked.
       constraint(document.getId(), "All versions except for PWC are locked when checked out.");
     }
   }
 }
  // 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);
  }