@Override
  public void insertEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
    Class<? extends MongoEntity> clazz = entity.getClass();

    // Find annotations for ID, for all the properties and for the name of the collection.
    EntityInfo entityInfo = getEntityInfo(clazz);

    // Create instance of BasicDBObject and add all declared properties to it (properties with null
    // value probably should be skipped)
    BasicDBObject dbObject =
        mapperRegistry.convertApplicationObjectToDBObject(entity, BasicDBObject.class);

    DBCollection dbCollection = database.getCollection(entityInfo.getDbCollectionName());

    String currentId = entity.getId();

    // Generate random ID if not set already
    if (currentId == null) {
      currentId = KeycloakModelUtils.generateId();
      entity.setId(currentId);
    }

    // Adding "_id"
    dbObject.put("_id", currentId);

    try {
      dbCollection.insert(dbObject);
    } catch (MongoException e) {
      throw convertException(e);
    }

    // Treat object as created in this transaction (It is already submited to transaction)
    context.addCreatedEntity(entity);
  }
  @Override
  public <S> boolean pushItemToList(
      final MongoIdentifiableEntity entity,
      final String listPropertyName,
      S itemToPush,
      boolean skipIfAlreadyPresent,
      MongoStoreInvocationContext context) {
    final Class<? extends MongoEntity> type = entity.getClass();
    EntityInfo entityInfo = getEntityInfo(type);

    // Add item to list directly in this object
    Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
    if (listProperty == null) {
      throw new IllegalArgumentException(
          "Property " + listPropertyName + " doesn't exist on object " + entity);
    }

    List<S> list = (List<S>) listProperty.getValue(entity);
    if (list == null) {
      list = new ArrayList<S>();
      listProperty.setValue(entity, list);
    }

    // Skip if item is already in list
    if (skipIfAlreadyPresent && list.contains(itemToPush)) {
      return false;
    }

    // Update java object
    list.add(itemToPush);

    // Add update of list to pending tasks
    final List<S> listt = list;
    context.addUpdateTask(
        entity,
        new MongoTask() {

          @Override
          public void execute() {
            // Now DB update of new list with usage of $set
            BasicDBList dbList =
                mapperRegistry.convertApplicationObjectToDBObject(listt, BasicDBList.class);

            BasicDBObject query = new BasicDBObject("_id", entity.getId());
            BasicDBObject listObject = new BasicDBObject(listPropertyName, dbList);
            BasicDBObject setCommand = new BasicDBObject("$set", listObject);
            getDBCollectionForType(type).update(query, setCommand);
          }

          @Override
          public boolean isFullUpdate() {
            return false;
          }
        });

    return true;
  }
  @Override
  public <S> boolean pullItemFromList(
      final MongoIdentifiableEntity entity,
      final String listPropertyName,
      final S itemToPull,
      MongoStoreInvocationContext context) {
    final Class<? extends MongoEntity> type = entity.getClass();
    EntityInfo entityInfo = getEntityInfo(type);

    // Remove item from list directly in this object
    Property<Object> listProperty = entityInfo.getPropertyByName(listPropertyName);
    if (listProperty == null) {
      throw new IllegalArgumentException(
          "Property " + listPropertyName + " doesn't exist on object " + entity);
    }
    List<S> list = (List<S>) listProperty.getValue(entity);

    // If list is null, we skip both object and DB update
    if (list == null || !list.contains(itemToPull)) {
      return false;
    } else {

      // Update java object
      list.remove(itemToPull);

      // Add update of list to pending tasks
      context.addUpdateTask(
          entity,
          new MongoTask() {

            @Override
            public void execute() {
              // Pull item from DB
              Object dbItemToPull =
                  mapperRegistry.convertApplicationObjectToDBObject(itemToPull, Object.class);
              BasicDBObject query = new BasicDBObject("_id", entity.getId());
              BasicDBObject pullObject = new BasicDBObject(listPropertyName, dbItemToPull);
              BasicDBObject pullCommand = new BasicDBObject("$pull", pullObject);
              getDBCollectionForType(type).update(query, pullCommand);
            }

            @Override
            public boolean isFullUpdate() {
              return false;
            }
          });

      return true;
    }
  }
 @Override
 public boolean removeEntity(MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
   return removeEntity(entity.getClass(), entity.getId(), context);
 }