@Override
 public void versioning(Document doc) {
   if (!doc.isLatestVersion() && !doc.isPrivateWorkingCopy()) {
     String msg = "The operation is not allowed on a non-current version of a document";
     throw new CmisVersioningException(buildMsgWithId(msg, doc.getId()), HTTP_STATUS_CODE_409);
   }
 }
  @Override
  public void setContentStream(
      CallContext callContext,
      String repositoryId,
      Holder<String> objectId,
      boolean overwriteFlag,
      ContentStream contentStream,
      Holder<String> changeToken) {

    exceptionService.invalidArgumentRequiredHolderString("objectId", objectId);

    Lock lock = threadLockService.getWriteLock(repositoryId, objectId.getValue());
    try {
      lock.lock();
      // //////////////////
      // General Exception
      // //////////////////

      exceptionService.invalidArgumentRequired("contentStream", contentStream);
      Document doc = (Document) contentService.getContent(repositoryId, objectId.getValue());
      exceptionService.objectNotFound(DomainType.OBJECT, doc, objectId.getValue());
      exceptionService.permissionDenied(
          callContext, repositoryId, PermissionMapping.CAN_SET_CONTENT_DOCUMENT, doc);
      DocumentTypeDefinition td =
          (DocumentTypeDefinition) typeManager.getTypeDefinition(repositoryId, doc.getObjectType());
      exceptionService.constraintImmutable(repositoryId, doc, td);

      // //////////////////
      // Specific Exception
      // //////////////////
      exceptionService.contentAlreadyExists(doc, overwriteFlag);
      exceptionService.streamNotSupported(td, contentStream);
      exceptionService.updateConflict(doc, changeToken);
      exceptionService.versioning(doc);
      Folder parent = contentService.getParent(repositoryId, objectId.getValue());
      exceptionService.objectNotFoundParentFolder(repositoryId, objectId.getValue(), parent);

      // //////////////////
      // Body of the method
      // //////////////////
      String oldId = objectId.getValue();

      // TODO Externalize versioningState
      if (doc.isPrivateWorkingCopy()) {
        Document result = contentService.replacePwc(callContext, repositoryId, doc, contentStream);
        objectId.setValue(result.getId());
      } else {
        Document result =
            contentService.createDocumentWithNewStream(
                callContext, repositoryId, doc, contentStream);
        objectId.setValue(result.getId());
      }

      nemakiCachePool.get(repositoryId).removeCmisCache(oldId);
    } finally {
      lock.unlock();
    }
  }
 @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 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);
  }