@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 deleteContentStream(
      CallContext callContext,
      String repositoryId,
      Holder<String> objectId,
      Holder<String> changeToken,
      ExtensionsData extension) {

    exceptionService.invalidArgumentRequiredHolderString("objectId", objectId);

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

      // //////////////////
      // Exception
      // //////////////////
      Document document = contentService.getDocument(repositoryId, objectId.getValue());
      exceptionService.objectNotFound(DomainType.OBJECT, document, document.getId());
      exceptionService.constraintContentStreamRequired(repositoryId, document);

      // //////////////////
      // Body of the method
      // //////////////////
      contentService.deleteContentStream(callContext, repositoryId, objectId);

      nemakiCachePool.get(repositoryId).removeCmisCache(objectId.getValue());

    } finally {
      lock.unlock();
    }
  }
 @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 String createDocumentFromSource(
      CallContext callContext,
      String repositoryId,
      String sourceId,
      Properties properties,
      String folderId,
      VersioningState versioningState,
      List<String> policies,
      Acl addAces,
      Acl removeAces) {
    Document original = contentService.getDocument(repositoryId, sourceId);
    DocumentTypeDefinition td =
        (DocumentTypeDefinition)
            typeManager.getTypeDefinition(repositoryId, original.getObjectType());

    // //////////////////
    // General Exception
    // //////////////////
    exceptionService.invalidArgumentRequired("properties", properties);
    exceptionService.invalidArgumentRequiredParentFolderId(repositoryId, folderId);
    Folder parentFolder = contentService.getFolder(repositoryId, folderId);
    exceptionService.objectNotFoundParentFolder(repositoryId, folderId, parentFolder);
    exceptionService.permissionDenied(
        callContext, repositoryId, PermissionMapping.CAN_CREATE_FOLDER_FOLDER, parentFolder);

    // //////////////////
    // Specific Exception
    // //////////////////
    exceptionService.constraintBaseTypeId(repositoryId, properties, BaseTypeId.CMIS_DOCUMENT);
    exceptionService.constraintAllowedChildObjectTypeId(parentFolder, properties);
    exceptionService.constraintPropertyValue(
        repositoryId, td, properties, DataUtil.getIdProperty(properties, PropertyIds.OBJECT_ID));
    exceptionService.constraintControllableVersionable(td, versioningState, null);
    versioningState =
        (td.isVersionable() && versioningState == null) ? VersioningState.MAJOR : versioningState;
    exceptionService.constraintCotrollablePolicies(td, policies, properties);
    exceptionService.constraintCotrollableAcl(td, addAces, removeAces, properties);
    exceptionService.constraintPermissionDefined(repositoryId, addAces, null);
    exceptionService.constraintPermissionDefined(repositoryId, removeAces, null);
    exceptionService.nameConstraintViolation(properties, parentFolder);

    // //////////////////
    // Body of the method
    // //////////////////
    Document document =
        contentService.createDocumentFromSource(
            callContext,
            repositoryId,
            properties,
            parentFolder,
            original,
            versioningState,
            policies,
            addAces,
            removeAces);
    return document.getId();
  }
 @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.");
     }
   }
 }
 @Override
 public void constraintContentStreamRequired(String repositoryId, Document document) {
   String objectTypeId = document.getObjectType();
   DocumentTypeDefinition td =
       (DocumentTypeDefinition) typeManager.getTypeDefinition(repositoryId, objectTypeId);
   if (td.getContentStreamAllowed() == ContentStreamAllowed.REQUIRED) {
     if (document.getAttachmentNodeId() == null
         || contentService.getAttachment(repositoryId, document.getAttachmentNodeId()) == null) {
       constraint(document.getId(), "This document type does not allow no content stream");
     }
   }
 }
 @Override
 public void constraintContentStreamDownload(String repositoryId, Document document) {
   DocumentTypeDefinition documentTypeDefinition =
       (DocumentTypeDefinition) typeManager.getTypeDefinition(repositoryId, document);
   ContentStreamAllowed csa = documentTypeDefinition.getContentStreamAllowed();
   if (ContentStreamAllowed.NOTALLOWED == csa
       || ContentStreamAllowed.ALLOWED == csa
           && StringUtils.isBlank(document.getAttachmentNodeId())) {
     constraint(
         document.getId(),
         "This document has no ContentStream. getContentStream is not supported.");
   }
 }
  @Override
  public void constraintImmutable(
      String repositoryId, Document document, TypeDefinition typeDefinition) {
    Boolean defaultVal =
        (Boolean)
            typeManager.getSingleDefaultValue(
                PropertyIds.IS_IMMUTABLE, typeDefinition.getId(), repositoryId);

    boolean flag = false;
    if (document.isImmutable() == null) {
      if (defaultVal != null && defaultVal) {
        flag = true;
      }
    } else {
      if (document.isImmutable()) {
        flag = true;
      }
    }

    if (flag) {
      constraint(document.getId(), "Immutable document cannot be updated/deleted");
    }
  }