private Content checkExceptionBeforeUpdateProperties(
      CallContext callContext,
      String repositoryId,
      Holder<String> objectId,
      Properties properties,
      Holder<String> changeToken) {
    // //////////////////
    // General Exception
    // //////////////////
    exceptionService.invalidArgumentRequiredCollection("properties", properties.getPropertyList());
    Content content = contentService.getContent(repositoryId, objectId.getValue());
    exceptionService.objectNotFound(DomainType.OBJECT, content, objectId.getValue());
    if (content.isDocument()) {
      Document d = (Document) content;
      exceptionService.versioning(d);
      exceptionService.constraintUpdateWhenCheckedOut(repositoryId, callContext.getUsername(), d);
      TypeDefinition typeDef = typeManager.getTypeDefinition(repositoryId, d);
      exceptionService.constraintImmutable(repositoryId, d, typeDef);
    }
    exceptionService.permissionDenied(
        callContext, repositoryId, PermissionMapping.CAN_UPDATE_PROPERTIES_OBJECT, content);
    exceptionService.updateConflict(content, changeToken);

    TypeDefinition tdf = typeManager.getTypeDefinition(repositoryId, content);
    exceptionService.constraintPropertyValue(repositoryId, tdf, properties, objectId.getValue());

    return content;
  }
  @Override
  public String createRelationship(
      CallContext callContext,
      String repositoryId,
      Properties properties,
      List<String> policies,
      Acl addAces,
      Acl removeAces,
      ExtensionsData extension) {
    String objectTypeId = DataUtil.getIdProperty(properties, PropertyIds.OBJECT_TYPE_ID);
    RelationshipTypeDefinition td =
        (RelationshipTypeDefinition) typeManager.getTypeDefinition(repositoryId, objectTypeId);
    // //////////////////
    // Exception
    // //////////////////
    exceptionService.invalidArgumentRequiredCollection("properties", properties.getPropertyList());
    String sourceId = DataUtil.getIdProperty(properties, PropertyIds.SOURCE_ID);
    if (sourceId != null) {
      Content source = contentService.getContent(repositoryId, sourceId);
      if (source == null) exceptionService.constraintAllowedSourceTypes(td, source);
      exceptionService.permissionDenied(
          callContext, repositoryId, PermissionMapping.CAN_CREATE_RELATIONSHIP_SOURCE, source);
    }
    String targetId = DataUtil.getIdProperty(properties, PropertyIds.TARGET_ID);
    if (targetId != null) {
      Content target = contentService.getContent(repositoryId, targetId);
      if (target == null) exceptionService.constraintAllowedTargetTypes(td, target);
      exceptionService.permissionDenied(
          callContext, repositoryId, PermissionMapping.CAN_CREATE_RELATIONSHIP_TARGET, target);
    }

    exceptionService.constraintBaseTypeId(repositoryId, properties, BaseTypeId.CMIS_RELATIONSHIP);
    exceptionService.constraintPropertyValue(
        repositoryId, td, properties, DataUtil.getIdProperty(properties, PropertyIds.OBJECT_ID));
    exceptionService.constraintCotrollablePolicies(td, policies, properties);
    exceptionService.constraintCotrollableAcl(td, addAces, removeAces, properties);
    exceptionService.constraintPermissionDefined(repositoryId, addAces, null);
    exceptionService.constraintPermissionDefined(repositoryId, removeAces, null);
    exceptionService.nameConstraintViolation(properties, null);

    // //////////////////
    // Body of the method
    // //////////////////
    Relationship relationship =
        contentService.createRelationship(
            callContext, repositoryId, properties, policies, addAces, removeAces, extension);
    nemakiCachePool.get(repositoryId).removeCmisCache(relationship.getSourceId());
    nemakiCachePool.get(repositoryId).removeCmisCache(relationship.getTargetId());

    return relationship.getId();
  }
  @Override
  public <T> void constraintPropertyValue(
      String repositoryId, TypeDefinition typeDefinition, Properties properties, String objectId) {
    Map<String, PropertyDefinition<?>> propertyDefinitions =
        typeDefinition.getPropertyDefinitions();

    // Adding secondary types and its properties MAY be done in the same
    // operation
    List<String> secIds =
        DataUtil.getIdListProperty(properties, PropertyIds.SECONDARY_OBJECT_TYPE_IDS);
    if (CollectionUtils.isNotEmpty(secIds)) {
      for (String secId : secIds) {
        TypeDefinition sec = typeManager.getTypeById(repositoryId, secId).getTypeDefinition();
        for (Entry<String, PropertyDefinition<?>> entry : sec.getPropertyDefinitions().entrySet()) {
          if (!propertyDefinitions.containsKey(entry.getKey())) {
            propertyDefinitions.put(entry.getKey(), entry.getValue());
          }
        }
      }
    }

    for (PropertyData<?> _pd : properties.getPropertyList()) {
      PropertyData<T> pd = (PropertyData<T>) _pd;
      PropertyDefinition<T> propertyDefinition =
          (PropertyDefinition<T>) propertyDefinitions.get(pd.getId());
      // If an input property is not defined one, output error.
      if (propertyDefinition == null) constraint(objectId, "An undefined property is provided!");

      // Check "required" flag
      if (propertyDefinition.isRequired() && !DataUtil.valueExist(pd.getValues()))
        constraint(objectId, "An required property is not provided!");

      // Check choices
      constraintChoices(propertyDefinition, pd, objectId);

      // Check min/max length
      switch (propertyDefinition.getPropertyType()) {
        case STRING:
          constraintStringPropertyValue(propertyDefinition, pd, objectId);
          break;
        case DECIMAL:
          constraintDecimalPropertyValue(propertyDefinition, pd, objectId);
        case INTEGER:
          constraintIntegerPropertyValue(propertyDefinition, pd, objectId);
          break;
        default:
          break;
      }
    }
  }
  @Override
  public String createItem(
      CallContext callContext,
      String repositoryId,
      Properties properties,
      String folderId,
      List<String> policies,
      Acl addAces,
      Acl removeAces,
      ExtensionsData extension) {
    // //////////////////
    // General Exception
    // //////////////////
    TypeDefinition td =
        typeManager.getTypeDefinition(repositoryId, DataUtil.getObjectTypeId(properties));
    Folder parentFolder = contentService.getFolder(repositoryId, folderId);
    exceptionService.objectNotFoundParentFolder(repositoryId, folderId, parentFolder);
    exceptionService.invalidArgumentRequiredCollection("properties", properties.getPropertyList());

    // //////////////////
    // Specific Exception
    // //////////////////
    exceptionService.constraintBaseTypeId(repositoryId, properties, BaseTypeId.CMIS_ITEM);
    exceptionService.constraintPropertyValue(
        repositoryId, td, properties, DataUtil.getIdProperty(properties, PropertyIds.OBJECT_ID));
    exceptionService.constraintCotrollablePolicies(td, policies, properties);
    exceptionService.constraintCotrollableAcl(td, addAces, removeAces, properties);

    // //////////////////
    // Body of the method
    // //////////////////
    Item item =
        contentService.createItem(
            callContext,
            repositoryId,
            properties,
            folderId,
            policies,
            addAces,
            removeAces,
            extension);
    return item.getId();
  }
  @Override
  public String createPolicy(
      CallContext callContext,
      String repositoryId,
      Properties properties,
      String folderId,
      List<String> policies,
      Acl addAces,
      Acl removeAces,
      ExtensionsData extension) {
    // //////////////////
    // General Exception
    // //////////////////
    exceptionService.invalidArgumentRequiredCollection("properties", properties.getPropertyList());
    // NOTE: folderId is ignored because policy is not filable in Nemaki
    TypeDefinition td =
        typeManager.getTypeDefinition(
            repositoryId, DataUtil.getIdProperty(properties, PropertyIds.OBJECT_TYPE_ID));
    exceptionService.constraintPropertyValue(
        repositoryId, td, properties, DataUtil.getIdProperty(properties, PropertyIds.OBJECT_ID));

    // //////////////////
    // Specific Exception
    // //////////////////
    exceptionService.constraintBaseTypeId(repositoryId, properties, BaseTypeId.CMIS_POLICY);
    // exceptionService.constraintAllowedChildObjectTypeId(parent,
    // properties);
    exceptionService.constraintCotrollablePolicies(td, policies, properties);
    exceptionService.constraintCotrollableAcl(td, addAces, removeAces, properties);
    // exceptionService.nameConstraintViolation(properties, parent);

    // //////////////////
    // Body of the method
    // //////////////////
    Policy policy =
        contentService.createPolicy(
            callContext, repositoryId, properties, policies, addAces, removeAces, extension);
    return policy.getId();
  }